Some fixes to the current RMI interrupt handling, changes in this patch are:

- (cleanup) remove rmi specific 'struct mips_intrhand' - this is no
longer needed since 'struct intr_event' have all the required hooks
- add xlr_cpu_establish_hardintr, which has args for pre/post ithread
and filter hooks, so that the PCI code can add the PCI controller
interrupt ack code here
- make 'cpu_establish_hardintr' use the above function.
- (fix) change type of eirr/eimr from register_t to uint64_t. These
have to be 64bit otherwise we cannot handle interrupts from 32.
- (fix) use eimr to mask eirr before checking interrupts, so that we
will not handle masked interrupts.

Obtained from:  C. Jayachandran - c.jayachandran@gmail.com
This commit is contained in:
Randall Stewart 2010-02-20 16:30:29 +00:00
parent d91c59ee1e
commit 0364c7f075
3 changed files with 45 additions and 35 deletions

View File

@ -30,21 +30,7 @@
#define _MACHINE_INTR_MACHDEP_H_
#ifdef TARGET_XLR_XLS
/*
* XLR/XLS uses its own intr_machdep.c and has
* a different number of interupts. This probably
* should be placed somewhere else.
*/
struct mips_intrhand {
struct intr_event *mih_event;
driver_intr_t *mih_disable;
volatile long *cntp; /* interrupt counter */
};
extern struct mips_intrhand mips_intr_handlers[];
#define XLR_MAX_INTR 64
#else
#define NHARD_IRQS 6
#define NSOFT_IRQS 2

View File

@ -25,7 +25,7 @@
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
*__FBSDID("$FreeBSD$")
* RMI_BSD */
#ifndef _RMI_INTERRUPT_H_
#define _RMI_INTERRUPT_H_
@ -39,4 +39,14 @@
#define IRQ_MSGRING 6
#define IRQ_TIMER 7
/*
* XLR needs custom pre and post handlers for PCI/PCI-e interrupts
* XXX: maybe follow i386 intsrc model
*/
void xlr_cpu_establish_hardintr(const char *, driver_filter_t *,
driver_intr_t *, void *, int, int, void **, void (*)(void *),
void (*)(void *), void (*)(void *), int (*)(void *, u_char));
void xlr_mask_hard_irq(void *);
void xlr_unmask_hard_irq(void *);
#endif /* _RMI_INTERRUPT_H_ */

View File

@ -51,19 +51,19 @@ __FBSDID("$FreeBSD$");
/*#include <machine/intrcnt.h>*/
static mips_intrcnt_t mips_intr_counters[XLR_MAX_INTR];
struct mips_intrhand mips_intr_handlers[XLR_MAX_INTR];
static struct intr_event *mips_intr_events[XLR_MAX_INTR];
static int intrcnt_index;
static void
mips_mask_hard_irq(void *source)
void
xlr_mask_hard_irq(void *source)
{
uintptr_t irq = (uintptr_t) source;
write_c0_eimr64(read_c0_eimr64() & ~(1ULL << irq));
}
static void
mips_unmask_hard_irq(void *source)
void
xlr_unmask_hard_irq(void *source)
{
uintptr_t irq = (uintptr_t) source;
@ -71,10 +71,11 @@ mips_unmask_hard_irq(void *source)
}
void
cpu_establish_hardintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags, void **cookiep)
xlr_cpu_establish_hardintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags, void **cookiep,
void (*pre_ithread)(void *), void (*post_ithread)(void *),
void (*post_filter)(void *), int (*assign_cpu)(void *, u_char))
{
struct mips_intrhand *mih; /* descriptor for the IRQ */
struct intr_event *ie; /* descriptor for the IRQ */
int errcode;
@ -85,25 +86,33 @@ cpu_establish_hardintr(const char *name, driver_filter_t * filt,
* FIXME locking - not needed now, because we do this only on
* startup from CPU0
*/
mih = &mips_intr_handlers[irq];
ie = mips_intr_events[irq];
/* mih->cntp = &intrcnt[irq]; */
ie = mih->mih_event;
if (ie == NULL) {
errcode = intr_event_create(&ie, (void *)(uintptr_t) irq, 0,
irq, mips_mask_hard_irq, mips_unmask_hard_irq,
NULL, NULL, "hard intr%d:", irq);
irq, pre_ithread, post_ithread, post_filter, assign_cpu,
"hard intr%d:", irq);
if (errcode) {
printf("Could not create event for intr %d\n", irq);
return;
}
mips_intr_events[irq] = ie;
}
intr_event_add_handler(ie, name, filt, handler, arg,
intr_priority(flags), flags, cookiep);
mih->mih_event = ie;
mips_unmask_hard_irq((void *)(uintptr_t) irq);
xlr_unmask_hard_irq((void *)(uintptr_t) irq);
}
void
cpu_establish_hardintr(const char *name, driver_filter_t * filt,
void (*handler) (void *), void *arg, int irq, int flags, void **cookiep)
{
xlr_cpu_establish_hardintr(name, filt, handler, arg, irq,
flags, cookiep, xlr_mask_hard_irq, xlr_unmask_hard_irq,
NULL, NULL);
}
void
cpu_establish_softintr(const char *name, driver_filter_t * filt,
@ -111,20 +120,26 @@ cpu_establish_softintr(const char *name, driver_filter_t * filt,
void **cookiep)
{
/* we don't separate them into soft/hard like other mips */
cpu_establish_hardintr(name, filt, handler, arg, irq, flags, cookiep);
xlr_cpu_establish_hardintr(name, filt, handler, arg, irq,
flags, cookiep, xlr_mask_hard_irq, xlr_unmask_hard_irq,
NULL, NULL);
}
void
cpu_intr(struct trapframe *tf)
{
struct mips_intrhand *mih;
struct intr_event *ie;
register_t eirr;
uint64_t eirr, eimr;
int i;
critical_enter();
/* find a list of enabled interrupts */
eirr = read_c0_eirr64();
if (eirr == 0) {
eimr = read_c0_eimr64();
eirr &= eimr;
if (eirr == 0) {
critical_exit();
return;
}
@ -162,9 +177,8 @@ cpu_intr(struct trapframe *tf)
}
#endif
#endif
mih = &mips_intr_handlers[i];
ie = mips_intr_events[i];
/* atomic_add_long(mih->cntp, 1); */
ie = mih->mih_event;
write_c0_eirr64(1ULL << i);
pic_ack(i, 0);