+ enable nested interrupts. This change stopped silo overflow messages

at 115200bps.

+ disable all hard interrupts by default.

+ rewrite s3c2xx0_(un)mask_interrupt() to make them faster.
This commit is contained in:
bsh 2003-07-30 18:25:50 +00:00
parent b2fb48e943
commit 675f6328c9
3 changed files with 79 additions and 91 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: s3c2800_intr.c,v 1.5 2003/07/15 00:24:48 lukem Exp $ */
/* $NetBSD: s3c2800_intr.c,v 1.6 2003/07/30 18:25:50 bsh Exp $ */
/*
* Copyright (c) 2002 Fujitsu Component Limited
@ -38,7 +38,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: s3c2800_intr.c,v 1.5 2003/07/15 00:24:48 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: s3c2800_intr.c,v 1.6 2003/07/30 18:25:50 bsh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -60,7 +60,8 @@ struct s3c2xx0_intr_dispatch handler[ICU_LEN];
__volatile int softint_pending;
__volatile int current_spl_level;
__volatile int intr_mask;
__volatile int intr_mask; /* XXX: does this need to be volatile? */
__volatile int global_intr_mask = 0; /* mask some interrupts at all spl level */
/* interrupt masks for each level */
int s3c2xx0_imask[NIPL];
@ -101,36 +102,38 @@ s3c2800_irq_handler(struct clockframe *frame)
saved_spl_level = current_spl_level;
/* get pending IRQs */
irqbits = icreg(INTCTL_IRQPND) & ICU_INT_HWMASK;
while ((irqbits = icreg(INTCTL_IRQPND) & ICU_INT_HWMASK) != 0) {
for (irqno = ICU_LEN-1; irqno >= 0; --irqno)
if (irqbits & (1<<irqno))
break;
if (irqno < 0)
break;
for (irqno = 0; irqbits; ++irqno) {
if ((irqbits & (1 << irqno)) == 0)
continue;
/* raise spl to stop interrupts of lower priorities */
if (saved_spl_level < handler[irqno].level)
s3c2xx0_setipl(handler[irqno].level);
/* clear pending bit */
icreg(INTCTL_SRCPND) = PENDING_CLEAR_MASK & (1 << irqno);
#ifdef notyet
/* Enable interrupt */
#endif
enable_interrupts(I32_bit); /* allow nested interrupts */
(*handler[irqno].func) (
handler[irqno].cookie == 0
? frame : handler[irqno].cookie);
#ifdef notyet
/* Disable interrupt */
#endif
irqbits &= ~(1 << irqno);
}
disable_interrupts(I32_bit);
/* restore spl to that was when this interrupt happen */
s3c2xx0_setipl(saved_spl_level);
}
if (softint_pending & intr_mask)
s3c2xx0_do_pending();
s3c2xx0_do_pending(1);
}
static const u_char s3c2800_ist[] = {
@ -181,8 +184,7 @@ s3c2800_intr_establish(int irqno, int level, int type,
GPIO_EXTINTR, reg);
}
intr_mask = s3c2xx0_imask[current_spl_level];
*s3c2xx0_intr_mask_reg = intr_mask;
s3c2xx0_setipl(current_spl_level);
restore_interrupts(save);

View File

@ -1,8 +1,8 @@
/* $NetBSD: s3c2xx0_intr.c,v 1.4 2003/07/15 00:24:49 lukem Exp $ */
/* $NetBSD: s3c2xx0_intr.c,v 1.5 2003/07/30 18:25:50 bsh Exp $ */
/*
* Copyright (c) 2002 Fujitsu Component Limited
* Copyright (c) 2002 Genetec Corporation
* Copyright (c) 2002, 2003 Fujitsu Component Limited
* Copyright (c) 2002, 2003 Genetec Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -73,7 +73,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: s3c2xx0_intr.c,v 1.4 2003/07/15 00:24:49 lukem Exp $");
__KERNEL_RCSID(0, "$NetBSD: s3c2xx0_intr.c,v 1.5 2003/07/30 18:25:50 bsh Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -160,95 +160,60 @@ static void
init_interrupt_masks(void)
{
int i;
s3c2xx0_imask[IPL_NONE] = 0xffffffff;
for (i = IPL_BIO; i < IPL_SOFTSERIAL; ++i)
s3c2xx0_imask[i] = SI_TO_IRQBIT(SI_SOFTSERIAL);
for (; i < NIPL; ++i)
s3c2xx0_imask[i] = 0;
s3c2xx0_imask[IPL_NONE] = SI_TO_IRQBIT(SI_SOFTSERIAL) |
SI_TO_IRQBIT(SI_SOFTNET) | SI_TO_IRQBIT(SI_SOFTCLOCK) |
SI_TO_IRQBIT(SI_SOFT);
/*
* Initialize the soft interrupt masks to block themselves.
*/
s3c2xx0_imask[IPL_SOFT] = ~SI_TO_IRQBIT(SI_SOFT);
s3c2xx0_imask[IPL_SOFTCLOCK] = ~SI_TO_IRQBIT(SI_SOFTCLOCK);
s3c2xx0_imask[IPL_SOFTNET] = ~SI_TO_IRQBIT(SI_SOFTNET);
s3c2xx0_imask[IPL_SOFT] = SI_TO_IRQBIT(SI_SOFTSERIAL) |
SI_TO_IRQBIT(SI_SOFTNET) | SI_TO_IRQBIT(SI_SOFTCLOCK);
/*
* splsoftclock() is the only interface that users of the
* generic software interrupt facility have to block their
* soft intrs, so splsoftclock() must also block IPL_SOFT.
*/
s3c2xx0_imask[IPL_SOFTCLOCK] &= s3c2xx0_imask[IPL_SOFT];
s3c2xx0_imask[IPL_SOFTCLOCK] = SI_TO_IRQBIT(SI_SOFTSERIAL) |
SI_TO_IRQBIT(SI_SOFTNET);
/*
* splsoftnet() must also block splsoftclock(), since we don't
* want timer-driven network events to occur while we're
* processing incoming packets.
*/
s3c2xx0_imask[IPL_SOFTNET] &= s3c2xx0_imask[IPL_SOFTCLOCK];
s3c2xx0_imask[IPL_SOFTNET] = SI_TO_IRQBIT(SI_SOFTSERIAL);
for (i = IPL_BIO; i < IPL_SOFTSERIAL; ++i)
s3c2xx0_imask[i] = SI_TO_IRQBIT(SI_SOFTSERIAL);
for (; i < NIPL; ++i)
s3c2xx0_imask[i] = 0;
}
/*
* Disable/enable interrupts.
* This is for S3C2XX0's intergrated UART, which can't disable tx/rx
* interrupts without disabling tx/rx by means of UART regsiters.
*/
void
s3c2xx0_mask_interrupts(int mask)
{
int save = disable_interrupts(I32_bit);
int i;
for (i = 0; i < NIPL - 1; ++i)
s3c2xx0_imask[i] &= ~mask;
intr_mask = s3c2xx0_imask[current_spl_level];
*s3c2xx0_intr_mask_reg = intr_mask;
restore_interrupts(save);
}
void
s3c2xx0_unmask_interrupts(int mask)
{
int save = disable_interrupts(I32_bit);
int i;
for (i = 0; i < ICU_LEN; ++i) {
if ((mask & (1 << i)) == 0)
continue;
s3c2xx0_update_intr_masks(i, s3c2xx0_ilevel[i]);
}
intr_mask = s3c2xx0_imask[current_spl_level];
*s3c2xx0_intr_mask_reg = intr_mask;
restore_interrupts(save);
}
void
s3c2xx0_do_pending(void)
s3c2xx0_do_pending(int enable_int)
{
static __cpu_simple_lock_t processing = __SIMPLELOCK_UNLOCKED;
int oldirqstate, spl_save;
int oldirqstate, irqstate, spl_save;
if (__cpu_simple_lock_try(&processing) == 0)
return;
spl_save = current_spl_level;
oldirqstate = disable_interrupts(I32_bit);
oldirqstate = irqstate = disable_interrupts(I32_bit);
if (enable_int)
irqstate &= ~I32_bit;
#define DO_SOFTINT(si,ipl) \
if ((softint_pending & intr_mask) & SI_TO_IRQBIT(si)) { \
softint_pending &= ~SI_TO_IRQBIT(si); \
__raise(ipl); \
restore_interrupts(oldirqstate); \
restore_interrupts(irqstate); \
softintr_dispatch(si); \
oldirqstate = disable_interrupts(I32_bit); \
disable_interrupts(I32_bit); \
s3c2xx0_setipl(spl_save); \
}
@ -297,24 +262,28 @@ s3c2xx0_intr_init(struct s3c2xx0_intr_dispatch * dispatch_table, int icu_len)
_splraise(IPL_SERIAL);
enable_interrupts(I32_bit);
}
#undef splx
void
splx(int ipl)
{
s3c2xx0_splx(ipl);
}
#undef _splraise
int
_splraise(int ipl)
{
return s3c2xx0_splraise(ipl);
}
#undef _spllower
int
_spllower(int ipl)
{
return s3c2xx0_spllower(ipl);
}
#undef _setsoftintr
void
_setsoftintr(int si)

View File

@ -1,8 +1,8 @@
/* $NetBSD: s3c2xx0_intr.h,v 1.2 2003/01/02 23:37:59 thorpej Exp $ */
/* $NetBSD: s3c2xx0_intr.h,v 1.3 2003/07/30 18:25:50 bsh Exp $ */
/*
* Copyright (c) 2002 Fujitsu Component Limited
* Copyright (c) 2002 Genetec Corporation
* Copyright (c) 2002, 2003 Fujitsu Component Limited
* Copyright (c) 2002, 2003 Genetec Corporation
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -87,21 +87,38 @@ extern volatile uint32_t *s3c2xx0_intr_mask_reg;
extern __volatile int current_spl_level;
extern __volatile int intr_mask;
extern __volatile int global_intr_mask;
extern __volatile int softint_pending;
extern int s3c2xx0_imask[];
extern int s3c2xx0_ilevel[];
void s3c2xx0_do_pending(void);
void s3c2xx0_do_pending(int);
void s3c2xx0_update_intr_masks( int, int );
void s3c2xx0_mask_interrupts(int);
void s3c2xx0_unmask_interrupts(int);
static __inline void
s3c2xx0_mask_interrupts(int mask)
{
int save = disable_interrupts(I32_bit);
global_intr_mask |= mask;
*s3c2xx0_intr_mask_reg = intr_mask & ~global_intr_mask;
restore_interrupts(save);
}
static __inline void
s3c2xx0_unmask_interrupts(int mask)
{
int save = disable_interrupts(I32_bit);
global_intr_mask &= ~mask;
*s3c2xx0_intr_mask_reg = intr_mask & ~global_intr_mask;
restore_interrupts(save);
}
static __inline void
s3c2xx0_setipl(int new)
{
current_spl_level = new;
intr_mask = s3c2xx0_imask[current_spl_level];
*s3c2xx0_intr_mask_reg = intr_mask;
*s3c2xx0_intr_mask_reg = intr_mask & ~global_intr_mask;
}
@ -116,7 +133,7 @@ s3c2xx0_splx(int new)
/* If there are software interrupts to process, do it. */
if (softint_pending & intr_mask)
s3c2xx0_do_pending();
s3c2xx0_do_pending(0);
}
@ -152,7 +169,7 @@ s3c2xx0_setsoftintr(int si)
/* Process unmasked pending soft interrupts. */
if ( softint_pending & intr_mask )
s3c2xx0_do_pending();
s3c2xx0_do_pending(0);
}