summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2011-06-08 22:58:00 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2011-06-08 22:58:00 +0000
commitbd7d13658fab1cd3adf7e2d41c21cc355885f822 (patch)
treec1d6349ec9bbb01b8805cae5c3eceb7189e8c0e9 /sys
parent94978f7149e09caa9bf0530a292f03402322a834 (diff)
Ateempt to make pci_intr_disestablish() work for MSIs.
ok deraadt@
Diffstat (limited to 'sys')
-rw-r--r--sys/arch/i386/include/psl.h6
-rw-r--r--sys/arch/i386/pci/pci_machdep.c30
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, &reg) == 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);
}