linux/arch/m68k/kernel
Thomas Gleixner 09f90f6685 m68k: Simplify low level interrupt handling code
The low level interrupt entry code of m68k contains the following:

    add_preempt_count(HARDIRQ_OFFSET);

    do_IRQ();
	irq_enter();
	    add_preempt_count(HARDIRQ_OFFSET);
	handle_interrupt();    
	irq_exit();    
	    sub_preempt_count(HARDIRQ_OFFSET);
	    if (in_interrupt())
       	       return; <---- On m68k always taken!
	    if (local_softirq_pending())
       	       do_softirq();

    sub_preempt_count(HARDIRQ_OFFSET);
    if (in_hardirq())
       return;
    if (status_on_stack_has_interrupt_priority_mask > 0)
       return;
    if (local_softirq_pending())
       do_softirq();

    ret_from_exception:
	if (interrupted_context_is_kernel)
	   return:
	....

I tried to find a proper explanation for this, but the changelog is
sparse and there are no mails explaining it further. But obviously
this relates to the interrupt priority levels of the m68k and tries to
be extra clever with nested interrupts. Though this cleverness just
adds code bloat to the interrupt hotpath.

For the common case of non nested interrupts the code runs through two
extra conditionals to the only important one, which checks whether the
return is to kernel or user space.

For the nested case the checks for in_hardirq() and the priority mask
value on stack catch only the case where the nested interrupt happens
inside the hard irq context of the first interrupt. If the nested
interrupt happens while the first interrupt handles soft interrupts,
then these extra checks buy nothing. The nested interrupt will fall
through to the final kernel/user space return check at
ret_from_exception.

Changing the code flow in the following way:

    do_IRQ();
	irq_enter();
	    add_preempt_count(HARDIRQ_OFFSET);
	handle_interrupt();    
	irq_exit();    
	    sub_preempt_count(HARDIRQ_OFFSET);
	    if (in_interrupt())
       	       return;
	    if (local_softirq_pending())
       	       do_softirq();

    ret_from_exception:
	if (interrupted_context_is_kernel)
	   return:

makes the region protected by the hardirq count slightly smaller and
the softirq handling is invoked with a minimal deeper stack. But
otherwise it's completely functional equivalent and saves 104 bytes of
text in arch/m68k/kernel/entry.o.

This modification allows us further to get rid of the limitations
which m68k puts on the preempt_count layout, so we can make the
preempt count bits completely generic.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Michael Schmitz <schmitz@biophys.uni-duesseldorf.de>
Acked-by: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Linux/m68k <linux-m68k@vger.kernel.org>
Cc: Andreas Schwab <schwab@linux-m68k.org>
Link: http://lkml.kernel.org/r/alpine.DEB.2.02.1311112052360.30673@ionos.tec.linutronix.de
2013-11-13 20:21:46 +01:00
..
.gitignore m68k: Add vmlinux.lds to .gitignore 2009-01-12 20:56:32 +01:00
asm-offsets.c lib: Move fonts from drivers/video/console/ to lib/fonts/ 2013-06-28 10:28:22 +02:00
dma.c m68k: add support for DMA_BIDIRECTIONAL in dma support functions 2012-07-17 15:49:40 +10:00
entry.S m68k: Simplify low level interrupt handling code 2013-11-13 20:21:46 +01:00
head.S m68k/mac: Fix unexpected interrupt with CONFIG_EARLY_PRINTK 2013-05-31 10:43:18 +02:00
ints.c m68k: Simplify low level interrupt handling code 2013-11-13 20:21:46 +01:00
irq.c Disintegrate asm/system.h for M68K 2012-03-28 18:30:02 +01:00
m68k_ksyms.c m68k: handle presence of 64bit mul/div instructions cleanly 2011-12-24 21:47:57 +10:00
Makefile m68k: Sort out !CONFIG_MMU_SUN3 vs. CONFIG_HAS_DMA 2013-02-09 14:23:36 +01:00
module.c module.c: spelling s/postition/position/g 2012-07-20 10:38:35 +02:00
module.lds m68k: runtime patching infrastructure 2007-05-31 07:58:13 -07:00
pcibios.c ARCH: drivers remove __dev* attributes. 2013-01-03 15:57:13 -08:00
process.c m68k: Use generic idle loop 2013-04-08 17:39:26 +02:00
ptrace.c m68k: make syscall_trace_enter/leave exist for non-MMU classic m68k types 2012-06-12 11:58:29 +10:00
setup_mm.c m68k/atari: ROM port ISA adapter support 2013-04-16 21:08:11 +02:00
setup_no.c m68knommu: Mark functions only called from setup_arch() __init 2013-08-26 16:51:13 +10:00
setup.c m68k: merge m68k and m68knommu arch directories 2011-03-25 14:05:13 +10:00
signal.c m68k/coldfire: flush cache when creating the signal stack frame 2013-08-26 16:51:13 +10:00
sun3-head.S m68k: arch/m68k/kernel/sun3-head.S needs <linux/init.h> 2009-04-28 16:07:18 -07:00
sys_m68k.c m68k: switch to generic sys_execve()/kernel_execve() 2012-10-01 00:44:44 -04:00
syscalltable.S m68k: Wire up finit_module 2012-12-25 20:14:56 +01:00
time.c PTR_RET is now PTR_ERR_OR_ZERO(): Replace most. 2013-07-15 11:25:01 +09:30
traps.c dump_stack: consolidate dump_stack() implementations and unify their behaviors 2013-04-30 17:04:02 -07:00
vectors.c Disintegrate asm/system.h for M68K 2012-03-28 18:30:02 +01:00
vmlinux-nommu.lds m68k: Replace m68k-specific _[se]bss by generic __bss_{start,stop} 2012-06-27 09:59:43 +02:00
vmlinux-std.lds m68k: Replace m68k-specific _[se]bss by generic __bss_{start,stop} 2012-06-27 09:59:43 +02:00
vmlinux-sun3.lds m68k: Replace m68k-specific _[se]bss by generic __bss_{start,stop} 2012-06-27 09:59:43 +02:00
vmlinux.lds.S m68k: use non-MMU linker script for ColdFire MMU builds 2011-12-30 10:20:44 +10:00