diff options
author | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-06-08 22:58:00 +0000 |
---|---|---|
committer | Mark Kettenis <kettenis@cvs.openbsd.org> | 2011-06-08 22:58:00 +0000 |
commit | bd7d13658fab1cd3adf7e2d41c21cc355885f822 (patch) | |
tree | c1d6349ec9bbb01b8805cae5c3eceb7189e8c0e9 /sys | |
parent | 94978f7149e09caa9bf0530a292f03402322a834 (diff) |
Ateempt to make pci_intr_disestablish() work for MSIs.
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/arch/i386/include/psl.h | 6 | ||||
-rw-r--r-- | sys/arch/i386/pci/pci_machdep.c | 30 |
2 files changed, 31 insertions, 5 deletions
diff --git a/sys/arch/i386/include/psl.h b/sys/arch/i386/include/psl.h index ad7101c3c3e..6d4e12a3572 100644 --- a/sys/arch/i386/include/psl.h +++ b/sys/arch/i386/include/psl.h @@ -1,4 +1,4 @@ -/* $OpenBSD: psl.h,v 1.18 2011/04/16 00:40:58 deraadt Exp $ */ +/* $OpenBSD: psl.h,v 1.19 2011/06/08 22:57:59 kettenis Exp $ */ /* $NetBSD: psl.h,v 1.30 1996/05/13 01:28:05 mycroft Exp $ */ /*- @@ -85,10 +85,12 @@ struct intrhand { int (*ih_fun)(void *); void *ih_arg; - struct intrhand *ih_next; int ih_level; + struct intrhand *ih_next; + int ih_pin; int ih_irq; struct evcount ih_count; + int ih_vec; }; extern int intr_shared_edge; /* This system has shared edge interrupts */ diff --git a/sys/arch/i386/pci/pci_machdep.c b/sys/arch/i386/pci/pci_machdep.c index 13f4e92a488..0b39b27c92d 100644 --- a/sys/arch/i386/pci/pci_machdep.c +++ b/sys/arch/i386/pci/pci_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci_machdep.c,v 1.62 2011/05/30 19:24:28 kettenis Exp $ */ +/* $OpenBSD: pci_machdep.c,v 1.63 2011/06/08 22:57:59 kettenis Exp $ */ /* $NetBSD: pci_machdep.c,v 1.28 1997/06/06 23:29:17 thorpej Exp $ */ /*- @@ -764,6 +764,7 @@ pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, int bus, dev; int l = ih.line & APIC_INT_LINE_MASK; pcitag_t tag = ih.tag; + int irq = ih.line; if (ih.line & APIC_INT_VIA_MSG) { struct intrhand *ih; @@ -785,8 +786,10 @@ pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, ih->ih_arg = arg; ih->ih_next = NULL; ih->ih_level = level; - ih->ih_irq = vec; - evcount_attach(&ih->ih_count, what, &ih->ih_irq); + ih->ih_irq = irq; + ih->ih_pin = tag.mode1; + ih->ih_vec = vec; + evcount_attach(&ih->ih_count, what, &ih->ih_vec); apic_maxlevel[vec] = level; apic_intrhand[vec] = ih; @@ -828,6 +831,27 @@ pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level, void pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie) { + struct intrhand *ih = cookie; + + if (ih->ih_irq & APIC_INT_VIA_MSG) { + pcitag_t tag = { .mode1 = ih->ih_pin }; + pcireg_t reg; + int off; + + if (pci_get_capability(pc, tag, PCI_CAP_MSI, &off, ®) == 0) + panic("%s: no msi capability", __func__); + + pci_conf_write(pc, tag, off, reg &= ~PCI_MSI_MC_MSIE); + + apic_maxlevel[ih->ih_vec] = 0; + apic_intrhand[ih->ih_vec] = NULL; + idt_vec_free(ih->ih_vec); + + evcount_detach(&ih->ih_count); + free(ih, M_DEVBUF); + return; + } + /* XXX oh, unroute the pci int link? */ isa_intr_disestablish(NULL, cookie); } |