+ 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:
parent
b2fb48e943
commit
675f6328c9
@ -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);
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user