linux/arch/alpha/kernel
Matt Turner 6f45effbd7 alpha: run the remote RTC access in a worker, not an IPI callback
On Marvel the CMOS clock is only reachable from the boot cpu, so
remote_read_time() and remote_set_time() bounce the access there with
smp_call_function_single(), whose callback runs in hard interrupt
context.

alpha_rtc_read_time() calls mc146818_get_time() with a 10 ms timeout.
That waits out the RTC update cycle in mc146818_avoid_UIP(), which drops
rtc_lock and udelay()s 100 us at a time until the update completes or
the timeout expires:

	for (i = 0; UIP_RECHECK_LOOPS_MS(i) < timeout; i++) {
		spin_lock_irqsave(&rtc_lock, flags);
		...
		if (CMOS_READ(RTC_FREQ_SELECT) & RTC_UIP) {
			spin_unlock_irqrestore(&rtc_lock, flags);
			udelay(UIP_RECHECK_DELAY);
			continue;
		}

So a clock read from a non-boot cpu can spin for up to 10 ms in hard
interrupt context on the boot cpu, while the cpu that sent the request
spins in smp_call_function_single() waiting for it to finish.

mc146818_set_time() does not poll, but it takes rtc_lock too, and
rtc_lock is a spinlock_t.  Only raw spinlocks may be taken in hard
interrupt context, so lockdep reports the write path as soon as a
non-boot cpu sets the clock:

  [ BUG: Invalid wait context ]
  -----------------------------
  swapper/0/0 is trying to lock:
  fffffc0003690470 (rtc_lock){....}-{3:3}, at: mc146818_set_time+0x74/0x450
  other info that might help us debug this:
  context-{2:2}
  no locks held by swapper/0/0.
  stack backtrace:
  CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.2.0-rc1 #1 NONE
  Trace:
  [<fffffc000102ebb0>] dump_stack+0x28/0x44
  [<fffffc000110efcc>] __lock_acquire+0xb0c/0x1060
  [<fffffc000110f5f0>] lock_acquire.part.0+0xd0/0x300
  [...]
  [<fffffc0001b0d834>] mc146818_set_time+0x74/0x450
  [<fffffc0001f090cc>] _raw_spin_lock_irqsave+0x7c/0xc0
  [<fffffc0001042f90>] do_remote_set+0x90/0xc0
  [<fffffc000119c1a4>] __flush_smp_call_function_queue+0x314/0x5c0
  [<fffffc000119c474>] generic_smp_call_function_single_interrupt+0x24/0x40
  [<fffffc000103d984>] handle_ipi+0xa4/0x230
  [<fffffc0001037044>] do_entInt+0x1a4/0x2e0

The rtc class ops are always called from process context, so there is no
reason to run the access from an interrupt at all.  Use work_on_cpu() to
run it in a worker on the boot cpu.  Alpha does not support cpu hotplug,
so the boot cpu cannot go offline while the work is pending.

Tested on an AlphaServer ES47 (Marvel/EV7): hwclock read and write
pinned to a non-boot cpu, twenty times, with no splat.

Signed-off-by: Matt Turner <mattst88@gmail.com>
Reviewed-by: Magnus Lindholm <linmag7@gmail.com>
Link: https://lore.kernel.org/r/20260810202835.3592833-1-mattst88@gmail.com
Signed-off-by: Magnus Lindholm <linmag7@gmail.com>
2026-08-11 23:23:47 +02:00
..
syscalls rseq: Implement sys_rseq_slice_yield() 2026-01-22 11:11:17 +01:00
.gitignore .gitignore: add SPDX License Identifier 2020-03-25 11:50:48 +01:00
asm-offsets.c alpha: enable regset-based ptrace and core dumps 2026-07-19 13:15:40 +02:00
audit.c audit: add support for the openat2 syscall 2021-10-01 16:52:48 -04:00
bugs.c alpha: missing includes 2024-05-03 22:09:30 +02:00
console.c alpha: missing includes 2024-05-03 22:09:30 +02:00
core_cia.c mm/memblock: add memblock_alloc_or_panic interface 2025-01-25 20:22:38 -08:00
core_irongate.c alpha: missing includes 2024-05-03 22:09:30 +02:00
core_marvel.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
core_mcpcia.c memblock: stop using implicit alignment to SMP_CACHE_BYTES 2018-10-31 08:54:16 -07:00
core_polaris.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
core_t2.c alpha: jensen, t2 - make __EXTERN_INLINE same as for the rest 2024-05-03 22:09:37 +02:00
core_titan.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
core_tsunami.c memblock: stop using implicit alignment to SMP_CACHE_BYTES 2018-10-31 08:54:16 -07:00
core_wildfire.c alpha: don't make functions public without a reason 2024-05-03 22:09:21 +02:00
entry.S alpha: enable lockdep hardirq state tracking 2026-07-19 13:16:26 +02:00
err_common.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
err_ev6.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
err_ev7.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
err_impl.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
err_marvel.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
err_titan.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
es1888.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
gct.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
head.S License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
io.c console: mdacon: remove this obsolete driver 2026-05-20 20:23:32 +02:00
irq_alpha.c alpha: enable lockdep hardirq state tracking 2026-07-19 13:16:26 +02:00
irq_i8259.c alpha: use raw spinlocks for low-level platform locks 2026-07-19 13:16:15 +02:00
irq_impl.h alpha: Replace setup_irq() by request_irq() 2020-03-29 21:03:41 +02:00
irq_pyxis.c alpha: Replace setup_irq() by request_irq() 2020-03-29 21:03:41 +02:00
irq_srm.c License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
irq.c genirq/proc: Increase default interrupt number precision to four 2026-05-26 16:21:14 +02:00
machvec_impl.h alpha: drop pre-EV56 support 2024-05-06 12:05:00 +02:00
Makefile alpha: add ARCH_STACKWALK-based stacktrace support 2026-07-19 13:15:54 +02:00
module.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
osf_sys.c alpha: switch osf_mount() to strndup_user() 2026-01-16 12:52:04 -05:00
pc873xx.c alpha: eliminate old-style function definitions 2021-05-06 19:24:11 -07:00
pc873xx.h License cleanup: add SPDX GPL-2.0 license identifier to files with no license 2017-11-02 11:10:55 +01:00
pci_impl.h alpha: remove LCA and APECS based machines 2024-05-03 22:09:59 +02:00
pci_iommu.c alpha: Convert mapping routine to rely on physical address 2025-10-29 10:27:30 +01:00
pci-sysfs.c PCI/sysfs: Convert legacy I/O and memory attributes to static definitions 2026-06-23 15:19:09 -05:00
pci.c resource: Pass full extent of empty space to resource_alignf callback 2026-03-27 10:18:39 -05:00
perf_event.c alpha/perf: Remove driver-specific throttle support 2025-05-21 13:57:45 +02:00
process.c arch: copy_thread: pass clone_flags as u64 2025-09-01 15:31:34 +02:00
proto.h alpha: enable lockdep hardirq state tracking 2026-07-19 13:16:26 +02:00
ptrace.c alpha: enable regset-based ptrace and core dumps 2026-07-19 13:15:40 +02:00
rtc.c alpha: run the remote RTC access in a worker, not an IPI callback 2026-08-11 23:23:47 +02:00
setup.c Convert 'alloc_obj' family to use the new default GFP_KERNEL argument 2026-02-21 17:09:51 -08:00
signal.c alpha: enable lockdep hardirq state tracking 2026-07-19 13:16:26 +02:00
smc37c93x.c alpha: missing includes 2024-05-03 22:09:30 +02:00
smc37c669.c alpha: missing includes 2024-05-03 22:09:30 +02:00
smp.c alpha: missing includes 2024-05-03 22:09:30 +02:00
srm_env.c proc: remove PDE_DATA() completely 2022-01-22 08:33:37 +02:00
srmcons.c treewide, timers: Rename from_timer() to timer_container_of() 2025-06-08 09:07:37 +02:00
stacktrace.c alpha: add ARCH_STACKWALK-based stacktrace support 2026-07-19 13:15:54 +02:00
sys_alcor.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
sys_cabriolet.c alpha: cabriolet: remove EV5 CPU support 2024-05-03 22:10:03 +02:00
sys_dp264.c alpha: use raw spinlocks for low-level platform locks 2026-07-19 13:16:15 +02:00
sys_eiger.c alpha: remove unneeded semicolon in sys_eiger.c 2020-06-12 17:43:17 -07:00
sys_marvel.c alpha: marvel: Fix lock ordering in init_io7_irqs() 2026-07-06 22:59:19 +02:00
sys_miata.c alpha: Streamline convoluted PCI error handling 2023-10-10 16:26:56 -05:00
sys_mikasa.c alpha: remove LCA and APECS based machines 2024-05-03 22:09:59 +02:00
sys_nautilus.c alpha: missing includes 2024-05-03 22:09:30 +02:00
sys_noritake.c alpha: remove LCA and APECS based machines 2024-05-03 22:09:59 +02:00
sys_rawhide.c alpha: use raw spinlocks for low-level platform locks 2026-07-19 13:16:15 +02:00
sys_ruffian.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
sys_rx164.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
sys_sable.c alpha: sable: remove early machine support 2024-05-03 22:09:55 +02:00
sys_sx164.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
sys_takara.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
sys_titan.c mm: don't include asm/pgtable.h if linux/mm.h is already included 2020-06-09 09:39:13 -07:00
sys_wildfire.c alpha: remove DISCONTIGMEM and NUMA 2021-06-29 10:53:55 -07:00
systbls.S alpha: syscalls: switch to generic syscalltbl.sh 2021-04-25 05:25:22 +09:00
termios.c termios: start unifying non-UAPI parts of asm/termios.h 2022-09-09 10:44:34 +02:00
time.c alpha: Replace setup_irq() by request_irq() 2020-03-29 21:03:41 +02:00
traps.c alpha: don't leak hardware-fabricated FP exception bits to user space 2026-08-11 23:07:54 +02:00
vmlinux.lds.S alpha: add ARCH_STACKWALK-based stacktrace support 2026-07-19 13:15:54 +02:00