Commit 7b275523 authored by Jesper Nilsson's avatar Jesper Nilsson Committed by Linus Torvalds

cris build fixes: corrected and improved NMI and IRQ handling

Corrects compile errors and the following:

- Remove oldset parameter from do_signal and do_notify_resume.

- Modified to fit new consolidated IRQ handling code.

- Reverse check order between external nmi and watchdog nmi to avoid false
  watchdog oops in case of a glitch on the nmi pin.

- Return from an pin-generated NMI the same way as for other interrupts.

- Moved blocking of ethernet rx/tx irq from ethernet interrupt handler to
  low-level asm interrupt handlers.  Fixed in the multiple interrupt
  handler also.

- Add space for thread local storage in thread_info struct.

- Add NO_DMA to Kconfig, and include arch specific Kconfig using arch
  independent path. Include subsystem Kconfigs for pcmcia, usb, i2c,
  rtc and pci.
Signed-off-by: default avatarJesper Nilsson <jesper.nilsson@axis.com>
Acked-by: default avatarMikael Starvik <starvik@axis.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 633edf5a
...@@ -13,6 +13,10 @@ config ZONE_DMA ...@@ -13,6 +13,10 @@ config ZONE_DMA
bool bool
default y default y
config NO_DMA
bool
default y
config RWSEM_GENERIC_SPINLOCK config RWSEM_GENERIC_SPINLOCK
bool bool
default y default y
...@@ -153,7 +157,8 @@ source "net/Kconfig" ...@@ -153,7 +157,8 @@ source "net/Kconfig"
# bring in ETRAX built-in drivers # bring in ETRAX built-in drivers
menu "Drivers for built-in interfaces" menu "Drivers for built-in interfaces"
source arch/cris/arch-v10/drivers/Kconfig # arch/cris/arch is a symlink to correct arch (arch-v10 or arch-v32)
source arch/cris/arch/drivers/Kconfig
endmenu endmenu
...@@ -184,6 +189,10 @@ source "drivers/isdn/Kconfig" ...@@ -184,6 +189,10 @@ source "drivers/isdn/Kconfig"
source "drivers/telephony/Kconfig" source "drivers/telephony/Kconfig"
source "drivers/i2c/Kconfig"
source "drivers/rtc/Kconfig"
# #
# input before char - char/joystick depends on it. As does USB. # input before char - char/joystick depends on it. As does USB.
# #
...@@ -198,6 +207,10 @@ source "fs/Kconfig" ...@@ -198,6 +207,10 @@ source "fs/Kconfig"
source "sound/Kconfig" source "sound/Kconfig"
source "drivers/pcmcia/Kconfig"
source "drivers/pci/Kconfig"
source "drivers/usb/Kconfig" source "drivers/usb/Kconfig"
source "kernel/Kconfig.instrumentation" source "kernel/Kconfig.instrumentation"
......
...@@ -2,6 +2,7 @@ config ETRAX_ETHERNET ...@@ -2,6 +2,7 @@ config ETRAX_ETHERNET
bool "Ethernet support" bool "Ethernet support"
depends on ETRAX_ARCH_V10 depends on ETRAX_ARCH_V10
select NET_ETHERNET select NET_ETHERNET
select MII
help help
This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
controller. controller.
......
...@@ -500,9 +500,8 @@ _work_notifysig: ...@@ -500,9 +500,8 @@ _work_notifysig:
;; deal with pending signals and notify-resume requests ;; deal with pending signals and notify-resume requests
move.d $r9, $r10 ; do_notify_resume syscall/irq param move.d $r9, $r10 ; do_notify_resume syscall/irq param
moveq 0, $r11 ; oldset param - 0 in this case move.d $sp, $r11 ; the regs param
move.d $sp, $r12 ; the regs param move.d $r1, $r12 ; the thread_info_flags parameter
move.d $r1, $r13 ; the thread_info_flags parameter
jsr do_notify_resume jsr do_notify_resume
ba _Rexit ba _Rexit
...@@ -678,13 +677,19 @@ IRQ1_interrupt: ...@@ -678,13 +677,19 @@ IRQ1_interrupt:
push $r10 ; push orig_r10 push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame clear.d [$sp=$sp-4] ; frametype == 0, normal frame
;; If there is a glitch on the NMI pin shorter than ~100ns
;; (i.e. non-active by the time we get here) then the nmi_pin bit
;; in R_IRQ_MASK0_RD will already be cleared. The watchdog_nmi bit
;; is cleared by us however (when feeding the watchdog), which is why
;; we use that bit to determine what brought us here.
move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog? move.d [R_IRQ_MASK0_RD], $r1 ; External NMI or watchdog?
and.d 0x80000000, $r1 and.d (1<<30), $r1
beq wdog bne wdog
move.d $sp, $r10 move.d $sp, $r10
jsr handle_nmi jsr handle_nmi
setf m ; Enable NMI again setf m ; Enable NMI again
retb ; Return from NMI ba _Rexit ; Return the standard way
nop nop
wdog: wdog:
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM) #if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
...@@ -775,22 +780,9 @@ multiple_interrupt: ...@@ -775,22 +780,9 @@ multiple_interrupt:
push $r10 ; push orig_r10 push $r10 ; push orig_r10
clear.d [$sp=$sp-4] ; frametype == 0, normal frame clear.d [$sp=$sp-4] ; frametype == 0, normal frame
moveq 2, $r2 ; first bit we care about is the timer0 irq move.d $sp, $r10
move.d [R_VECT_MASK_RD], $r0; read the irq bits that triggered the multiple irq jsr do_multiple_IRQ
move.d $r0, [R_VECT_MASK_CLR] ; Block all active IRQs
1:
btst $r2, $r0 ; check for the irq given by bit r2
bpl 2f
move.d $r2, $r10 ; First argument to do_IRQ
move.d $sp, $r11 ; second argument to do_IRQ
jsr do_IRQ
2:
addq 1, $r2 ; next vector bit
cmp.b 32, $r2
bne 1b ; process all irq's up to and including number 31
moveq 0, $r9 ; make ret_from_intr realise we came from an ir
move.d $r0, [R_VECT_MASK_SET] ; Unblock all the IRQs
jump ret_from_intr jump ret_from_intr
do_sigtrap: do_sigtrap:
...@@ -837,6 +829,13 @@ _ugdb_handle_breakpoint: ...@@ -837,6 +829,13 @@ _ugdb_handle_breakpoint:
ba do_sigtrap ; SIGTRAP the offending process. ba do_sigtrap ; SIGTRAP the offending process.
pop $dccr ; Restore dccr in delay slot. pop $dccr ; Restore dccr in delay slot.
.global kernel_execve
kernel_execve:
move.d __NR_execve, $r9
break 13
ret
nop
.data .data
hw_bp_trigs: hw_bp_trigs:
......
...@@ -12,10 +12,16 @@ ...@@ -12,10 +12,16 @@
*/ */
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/current.h>
#include <linux/irq.h> #include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/init.h> #include <linux/init.h>
/* From kgdb.c. */
extern void kgdb_init(void);
extern void breakpoint(void);
#define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr)); #define mask_irq(irq_nr) (*R_VECT_MASK_CLR = 1 << (irq_nr));
#define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr)); #define unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));
...@@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000) ...@@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000)
BUILD_IRQ(13, 0x2000) BUILD_IRQ(13, 0x2000)
void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */ void mmu_bus_fault(void); /* IRQ 14 is the bus fault interrupt */
void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */ void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
BUILD_IRQ(16, 0x10000) BUILD_IRQ(16, 0x10000 | 0x20000) /* ethernet tx interrupt needs to block rx */
BUILD_IRQ(17, 0x20000) BUILD_IRQ(17, 0x20000 | 0x10000) /* ...and vice versa */
BUILD_IRQ(18, 0x40000) BUILD_IRQ(18, 0x40000)
BUILD_IRQ(19, 0x80000) BUILD_IRQ(19, 0x80000)
BUILD_IRQ(20, 0x100000) BUILD_IRQ(20, 0x100000)
...@@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */ ...@@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */
void do_sigtrap(void); /* from entry.S */ void do_sigtrap(void); /* from entry.S */
void gdb_handle_breakpoint(void); /* from entry.S */ void gdb_handle_breakpoint(void); /* from entry.S */
extern void do_IRQ(int irq, struct pt_regs * regs);
/* Handle multiple IRQs */
void do_multiple_IRQ(struct pt_regs* regs)
{
int bit;
unsigned masked;
unsigned mask;
unsigned ethmask = 0;
/* Get interrupts to mask and handle */
mask = masked = *R_VECT_MASK_RD;
/* Never mask timer IRQ */
mask &= ~(IO_MASK(R_VECT_MASK_RD, timer0));
/*
* If either ethernet interrupt (rx or tx) is active then block
* the other one too. Unblock afterwards also.
*/
if (mask &
(IO_STATE(R_VECT_MASK_RD, dma0, active) |
IO_STATE(R_VECT_MASK_RD, dma1, active))) {
ethmask = (IO_MASK(R_VECT_MASK_RD, dma0) |
IO_MASK(R_VECT_MASK_RD, dma1));
}
/* Block them */
*R_VECT_MASK_CLR = (mask | ethmask);
/* An extra irq_enter here to prevent softIRQs to run after
* each do_IRQ. This will decrease the interrupt latency.
*/
irq_enter();
/* Handle all IRQs */
for (bit = 2; bit < 32; bit++) {
if (masked & (1 << bit)) {
do_IRQ(bit, regs);
}
}
/* This irq_exit() will trigger the soft IRQs. */
irq_exit();
/* Unblock the IRQs again */
*R_VECT_MASK_SET = (masked | ethmask);
}
/* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and /* init_IRQ() is called by start_kernel and is responsible for fixing IRQ masks and
setting the irq vector table. setting the irq vector table.
*/ */
......
...@@ -195,6 +195,11 @@ EXPORT_SYMBOL(enable_hlt); ...@@ -195,6 +195,11 @@ EXPORT_SYMBOL(enable_hlt);
*/ */
void (*pm_idle)(void); void (*pm_idle)(void);
extern void default_idle(void);
void (*pm_power_off)(void);
EXPORT_SYMBOL(pm_power_off);
/* /*
* The idle thread. There's no useful work to be * The idle thread. There's no useful work to be
* done, so just try to conserve power and have a * done, so just try to conserve power and have a
......
...@@ -81,13 +81,13 @@ ...@@ -81,13 +81,13 @@
/* notification of userspace execution resumption /* notification of userspace execution resumption
* - triggered by current->work.notify_resume * - triggered by current->work.notify_resume
*/ */
extern int do_signal(int canrestart, sigset_t *oldset, struct pt_regs *regs); extern int do_signal(int canrestart, struct pt_regs *regs);
void do_notify_resume(int canrestart, sigset_t *oldset, struct pt_regs *regs, void do_notify_resume(int canrestart, struct pt_regs *regs,
__u32 thread_info_flags ) __u32 thread_info_flags )
{ {
/* deal with pending signal delivery */ /* deal with pending signal delivery */
if (thread_info_flags & _TIF_SIGPENDING) if (thread_info_flags & _TIF_SIGPENDING)
do_signal(canrestart,oldset,regs); do_signal(canrestart,regs);
} }
...@@ -32,6 +32,7 @@ struct thread_info { ...@@ -32,6 +32,7 @@ struct thread_info {
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */ __u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable, <0 => BUG */ int preempt_count; /* 0 => preemptable, <0 => BUG */
__u32 tls; /* TLS for this thread */
mm_segment_t addr_limit; /* thread address space: mm_segment_t addr_limit; /* thread address space:
0-0xBFFFFFFF for user-thead 0-0xBFFFFFFF for user-thead
...@@ -79,14 +80,18 @@ struct thread_info { ...@@ -79,14 +80,18 @@ struct thread_info {
* - other flags in MSW * - other flags in MSW
*/ */
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */ #define TIF_SYSCALL_TRACE 0 /* syscall trace active */
#define TIF_SIGPENDING 1 /* signal pending */ #define TIF_NOTIFY_RESUME 1 /* resumption notification requested */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */ #define TIF_SIGPENDING 2 /* signal pending */
#define TIF_NEED_RESCHED 3 /* rescheduling necessary */
#define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */
#define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */ #define TIF_POLLING_NRFLAG 16 /* true if poll_idle() is polling TIF_NEED_RESCHED */
#define TIF_MEMDIE 17 #define TIF_MEMDIE 17
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
#define _TIF_SIGPENDING (1<<TIF_SIGPENDING) #define _TIF_SIGPENDING (1<<TIF_SIGPENDING)
#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED) #define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)
#define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK)
#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) #define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG)
#define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */ #define _TIF_WORK_MASK 0x0000FFFE /* work to do on interrupt/exception return */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment