Hi,
I find one interrupt issue on my coldfire platform on linux-2.6.29
version (mcf54451evb board, mmu, NFS as rootfs).
After system boot up, I do following test:
on target board, run command: nc -l -p 3333 > /dev/null &
on host PC, run command: dd if=/dev/zero | nc 10.192.208.230 (target ip)
3333
and then I run top command on target board to check, which is shown as
follows:
CPU: 0.5% usr 0.0% sys 0.0% nice 0.0% idle 0.0% io 99.4% irq 0.0%
softirq
Load average: 0.39 0.10 0.03
PID PPID USER STAT VSZ %MEM %CPU COMMAND
502 498 root R 2560 2.0 97.8 nc -l -p 3333
3 2 root SW< 0 0.0 1.3 [ksoftirqd/0]
503 498 root R 2832 2.2 0.4 top
492 1 root S 3952 3.1 0.2 nmbd -s /etc/samba/smb.conf
495 1 root S 6144 4.8 0.0 smbd -s /etc/samba/smb.conf
499 495 root S 6144 4.8 0.0 smbd -s /etc/samba/smb.conf
498 1 root S 3056 2.4 0.0 -/bin/sh
485 1 root S 2864 2.2 0.0 /usr/sbin/inetd
1 0 root S 2824 2.2 0.0 init
468 1 root S 2824 2.2 0.0 /sbin/syslogd
470 1 root S 2824 2.2 0.0 /sbin/klogd
488 1 nobody S 2672 2.1 0.0 /usr/sbin/boa -c /etc
297 1 root S < 2472 1.9 0.0 udevd --daemon
282 2 root SW< 0 0.0 0.0 [rpciod/0]
143 2 root SW< 0 0.0 0.0 [nfsiod]
6 2 root SW< 0 0.0 0.0 [khelper]
2 0 root SW< 0 0.0 0.0 [kthreadd]
4 2 root SW< 0 0.0 0.0 [watchdog/0]
5 2 root SW< 0 0.0 0.0 [events/0]
53 2 root SW< 0 0.0 0.0 [kblockd/0]
The irq time takes up most cpu time, but "softirq" and "sys" time is 0%.
I run /proc/stat to check, which is shown as follows:
[r...@freescale /]# cat /proc/stat
cpu 316 0 0 53838 409 14467 0 0 0
cpu0 316 0 0 53838 409 14467 0 0 0
intr 636215 2 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 2 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00
ctxt 281405
btime 0
processes 499
procs_running 2
procs_blocked 0
It's indeed that the statistic time number of "sys" and "softirq" is zero.
I tracked the source codes, and find the root cause is in following
codes (the Entry function for interrupt) in the entry.S:
ENTRY(inthandler)
SAVE_ALL_INT
GET_CURRENT(%d0)
* addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)*
/* put exception # in d0 */
movel %sp@(PT_VECTOR),%d0
swap %d0 /* extract bits 25:18 */
lsrl #2,%d0
andl #0x0ff,%d0
movel %sp,%...@-
movel %d0,%...@- /* put vector # on stack */
auto_irqhandler_fixup = . + 2
jbsr process_int /* process the IRQ */
addql #8,%sp /* pop parameters off stack */
*subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)*
jeq ret_from_last_interrupt
2: RESTORE_ALL
ALIGN
ret_from_last_interrupt:
moveb %sp@(PT_SR),%d0
andl #(~ALLOWINT>>8)&0xff,%d0
jne 2b
/* check if we need to do software interrupts */
tstl irq_stat+CPUSTAT_SOFTIRQ_PENDING
jeq .Lret_from_exception
pea ret_from_exception
jra do_softirq
My understanding of "*addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)*"
is that its meaning is equal to
"current_thread_info()->preempt_count += HARDIRQ_OFFSET", which shows
now it's interrupt context. And the
meaning of "*subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)*" should be
opposite.
However, it seems these two line codes doesn't take their responsibility
from above test result (I don't know why).
I comment these two lines and add "irq_enter() / irq_exit()" function
pairs into the process_int function (process_int() is the interrupt
handler).
My understanding the function of irq_enter()/irq_exit() is the same as
those two line assembly codes). Attached is my patch.
Following is my test result with my patch:
on target board, run command: nc -l -p 3333 > /dev/null &
on host PC, run command: dd if=/dev/zero | nc 10.192.208.230 (target ip)
3333
run top command on target:
CPU: 0.9% usr 24.1% sys 0.0% nice 0.0% idle 0.0% io 18.2% irq 56.6%
softirq
Load average: 0.28 0.12 0.06
PID PPID USER STAT VSZ %MEM %CPU COMMAND
498 495 root R 2560 2.0 99.2 nc -l -p 3333
499 495 root R 2832 2.2 0.4 top
489 1 root S 3952 3.1 0.2 nmbd -s /etc/samba/smb.conf
492 1 root S 6144 4.8 0.0 smbd -s /etc/samba/smb.conf
496 492 root S 6144 4.8 0.0 smbd -s /etc/samba/smb.conf
495 1 root S 3056 2.4 0.0 -/bin/sh
482 1 root S 2864 2.2 0.0 /usr/sbin/inetd
1 0 root S 2824 2.2 0.0 init
465 1 root S 2824 2.2 0.0 /sbin/syslogd
467 1 root S 2824 2.2 0.0 /sbin/klogd
485 1 nobody S 2672 2.1 0.0 /usr/sbin/boa -c /etc
297 1 root S < 2472 1.9 0.0 udevd --daemon
282 2 root SW< 0 0.0 0.0 [rpciod/0]
143 2 root SW< 0 0.0 0.0 [nfsiod]
6 2 root SW< 0 0.0 0.0 [khelper]
2 0 root SW< 0 0.0 0.0 [kthreadd]
3 2 root SW< 0 0.0 0.0 [ksoftirqd/0]
4 2 root SW< 0 0.0 0.0 [watchdog/0]
5 2 root SW< 0 0.0 0.0 [events/0]
53 2 root SW< 0 0.0 0.0 [kblockd/0]
run cat /proc/stat on target:
[r...@freescale /]# cat /proc/stat
cpu 281 0 3565 34268 475 2597 7452 0 0
cpu0 281 0 3565 34268 475 2597 7452 0 0
intr 522453 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0
0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 00
ctxt 18910
btime 0
processes 497
procs_running 2
procs_blocked 0
Any idea for this issue?
Regards,
Lanttor
diff --git a/arch/m68k/coldfire/entry.S b/arch/m68k/coldfire/entry.S
index 3fc1df8..cfd9349 100644
--- a/arch/m68k/coldfire/entry.S
+++ b/arch/m68k/coldfire/entry.S
@@ -232,7 +232,6 @@ do_delayed_trace:
ENTRY(inthandler)
SAVE_ALL_INT
GET_CURRENT(%d0)
- addql #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
/* put exception # in d0 */
movel %sp@(PT_VECTOR),%d0
swap %d0 /* extract bits 25:18 */
@@ -244,7 +243,6 @@ ENTRY(inthandler)
auto_irqhandler_fixup = . + 2
jbsr process_int /* process the IRQ */
addql #8,%sp /* pop parameters off stack */
- subql #1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
jeq ret_from_last_interrupt
2: RESTORE_ALL
diff --git a/arch/m68k/coldfire/ints.c b/arch/m68k/coldfire/ints.c
index 3316463..85ce27e 100644
--- a/arch/m68k/coldfire/ints.c
+++ b/arch/m68k/coldfire/ints.c
@@ -100,6 +100,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
old_regs = set_irq_regs(fp);
kstat_cpu(0).irqs[vec]++;
+ irq_enter();
node = irq_list[vec];
if (!node)
handle_badint(fp);
@@ -109,6 +110,7 @@ asmlinkage void process_int(unsigned long vec, struct pt_regs *fp)
node = node->next;
} while (node);
}
+ irq_exit();
set_irq_regs(old_regs);
}