Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+14 −1
Original line number Diff line number Diff line
@@ -13,6 +13,10 @@ config ZONE_DMA
	bool
	default y

config NO_DMA
	bool
	default y

config RWSEM_GENERIC_SPINLOCK
	bool
	default y
@@ -153,7 +157,8 @@ source "net/Kconfig"

# bring in ETRAX built-in drivers
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

@@ -184,6 +189,10 @@ source "drivers/isdn/Kconfig"

source "drivers/telephony/Kconfig"

source "drivers/i2c/Kconfig"

source "drivers/rtc/Kconfig"

#
# input before char - char/joystick depends on it. As does USB.
#
@@ -198,6 +207,10 @@ source "fs/Kconfig"

source "sound/Kconfig"

source "drivers/pcmcia/Kconfig"

source "drivers/pci/Kconfig"

source "drivers/usb/Kconfig"

source "kernel/Kconfig.instrumentation"
+1 −0
Original line number Diff line number Diff line
@@ -2,6 +2,7 @@ config ETRAX_ETHERNET
	bool "Ethernet support"
	depends on ETRAX_ARCH_V10
	select NET_ETHERNET
	select MII
	help
	  This option enables the ETRAX 100LX built-in 10/100Mbit Ethernet
	  controller.
+20 −21
Original line number Diff line number Diff line
@@ -500,9 +500,8 @@ _work_notifysig:
	;; deal with pending signals and notify-resume requests

	move.d	$r9, $r10	; do_notify_resume syscall/irq param
	moveq	0, $r11		; oldset param - 0 in this case
	move.d	$sp, $r12	; the regs param
	move.d  $r1, $r13	; the thread_info_flags parameter
	move.d	$sp, $r11	; the regs param
	move.d  $r1, $r12	; the thread_info_flags parameter
	jsr	do_notify_resume
	
	ba _Rexit
@@ -678,13 +677,19 @@ IRQ1_interrupt:
	push	$r10		; push orig_r10
	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?
	and.d   0x80000000, $r1
	beq	wdog
	and.d   (1<<30), $r1
	bne	wdog
	move.d  $sp, $r10
	jsr	handle_nmi
	setf m			; Enable NMI again
	retb			; Return from NMI
	ba	_Rexit		; Return the standard way
	nop
wdog:
#if defined(CONFIG_ETRAX_WATCHDOG) && !defined(CONFIG_SVINTO_SIM)
@@ -775,22 +780,9 @@ multiple_interrupt:
	push	$r10		; push orig_r10
	clear.d [$sp=$sp-4]	; frametype == 0, normal frame
	
	moveq	2, $r2		; first bit we care about is the timer0 irq
	move.d	[R_VECT_MASK_RD], $r0; read the irq bits that triggered the 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
	move.d  $sp, $r10
	jsr	do_multiple_IRQ
	
	jump    ret_from_intr

do_sigtrap:
@@ -837,6 +829,13 @@ _ugdb_handle_breakpoint:
	ba	do_sigtrap		; SIGTRAP the offending process. 
	pop	$dccr			; Restore dccr in delay slot.
	
	.global kernel_execve
kernel_execve:
	move.d __NR_execve, $r9
	break 13
	ret
	nop

	.data

hw_bp_trigs:
+57 −2
Original line number Diff line number Diff line
@@ -12,10 +12,16 @@
 */

#include <asm/irq.h>
#include <asm/current.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/kernel.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 unmask_irq(irq_nr) (*R_VECT_MASK_SET = 1 << (irq_nr));

@@ -75,8 +81,8 @@ BUILD_IRQ(12, 0x1000)
BUILD_IRQ(13, 0x2000)
void mmu_bus_fault(void);      /* IRQ 14 is the bus fault interrupt */
void multiple_interrupt(void); /* IRQ 15 is the multiple IRQ interrupt */
BUILD_IRQ(16, 0x10000)
BUILD_IRQ(17, 0x20000)
BUILD_IRQ(16, 0x10000 | 0x20000)  /* ethernet tx interrupt needs to block rx */
BUILD_IRQ(17, 0x20000 | 0x10000)  /* ...and vice versa */
BUILD_IRQ(18, 0x40000)
BUILD_IRQ(19, 0x80000)
BUILD_IRQ(20, 0x100000)
@@ -147,6 +153,55 @@ void system_call(void); /* from entry.S */
void do_sigtrap(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
   setting the irq vector table.
*/
+5 −0
Original line number Diff line number Diff line
@@ -195,6 +195,11 @@ EXPORT_SYMBOL(enable_hlt);
 */
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
 * done, so just try to conserve power and have a
Loading