Module Name: src
Committed By: nonaka
Date: Wed Oct 19 00:08:42 UTC 2016
Modified Files:
src/sys/arch/bebox/pci: pci_machdep.c
src/sys/arch/evbppc/pmppc/pci: pci_machdep.c
src/sys/arch/ibmnws/pci: pci_machdep.c
src/sys/arch/macppc/pci: pci_machdep.c
src/sys/arch/mvmeppc/pci: pci_machdep.c
src/sys/arch/ofppc/pci: ofwpci.c
src/sys/arch/powerpc/booke: e500_intr.c
src/sys/arch/powerpc/booke/pci: pq3pci.c
src/sys/arch/powerpc/ibm4xx/dev: ibm405gp.c
src/sys/arch/powerpc/include: cpu.h intr.h pci_machdep.h
src/sys/arch/powerpc/include/booke: intr.h
src/sys/arch/powerpc/marvell: pci_machdep.c
src/sys/arch/powerpc/pci: pci_machdep_common.c
src/sys/arch/powerpc/pic: intr.c
src/sys/arch/powerpc/powerpc: intr_stubs.c
src/sys/arch/prep/pci: pci_machdep.c prep_pciconf_direct.c
src/sys/arch/sandpoint/include: pci_machdep.h
src/sys/arch/sandpoint/pci: pci_machdep.c
Log Message:
Added MSI/MSI-X and interrupt_distribute(9) support for powerpc.
To generate a diff of this commit:
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/bebox/pci/pci_machdep.c
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/evbppc/pmppc/pci/pci_machdep.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/ibmnws/pci/pci_machdep.c
cvs rdiff -u -r1.40 -r1.41 src/sys/arch/macppc/pci/pci_machdep.c
cvs rdiff -u -r1.10 -r1.11 src/sys/arch/mvmeppc/pci/pci_machdep.c
cvs rdiff -u -r1.12 -r1.13 src/sys/arch/ofppc/pci/ofwpci.c
cvs rdiff -u -r1.33 -r1.34 src/sys/arch/powerpc/booke/e500_intr.c
cvs rdiff -u -r1.21 -r1.22 src/sys/arch/powerpc/booke/pci/pq3pci.c
cvs rdiff -u -r1.7 -r1.8 src/sys/arch/powerpc/ibm4xx/dev/ibm405gp.c
cvs rdiff -u -r1.101 -r1.102 src/sys/arch/powerpc/include/cpu.h
cvs rdiff -u -r1.11 -r1.12 src/sys/arch/powerpc/include/intr.h
cvs rdiff -u -r1.13 -r1.14 src/sys/arch/powerpc/include/pci_machdep.h
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/powerpc/include/booke/intr.h
cvs rdiff -u -r1.5 -r1.6 src/sys/arch/powerpc/marvell/pci_machdep.c
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/powerpc/pci/pci_machdep_common.c
cvs rdiff -u -r1.24 -r1.25 src/sys/arch/powerpc/pic/intr.c
cvs rdiff -u -r1.4 -r1.5 src/sys/arch/powerpc/powerpc/intr_stubs.c
cvs rdiff -u -r1.41 -r1.42 src/sys/arch/prep/pci/pci_machdep.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/prep/pci/prep_pciconf_direct.c
cvs rdiff -u -r1.9 -r1.10 src/sys/arch/sandpoint/include/pci_machdep.h
cvs rdiff -u -r1.34 -r1.35 src/sys/arch/sandpoint/pci/pci_machdep.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Modified files:
Index: src/sys/arch/bebox/pci/pci_machdep.c
diff -u src/sys/arch/bebox/pci/pci_machdep.c:1.21 src/sys/arch/bebox/pci/pci_machdep.c:1.22
--- src/sys/arch/bebox/pci/pci_machdep.c:1.21 Fri Jul 1 20:34:53 2011
+++ src/sys/arch/bebox/pci/pci_machdep.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.21 2011/07/01 20:34:53 dyoung Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.22 2016/10/19 00:08:41 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.21 2011/07/01 20:34:53 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.22 2016/10/19 00:08:41 nonaka Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -87,6 +87,16 @@ bebox_pci_get_chipset_tag(pci_chipset_ta
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = (void *)pc;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = bebox_pci_conf_interrupt;
pc->pc_decompose_tag = genppc_pci_indirect_decompose_tag;
Index: src/sys/arch/evbppc/pmppc/pci/pci_machdep.c
diff -u src/sys/arch/evbppc/pmppc/pci/pci_machdep.c:1.5 src/sys/arch/evbppc/pmppc/pci/pci_machdep.c:1.6
--- src/sys/arch/evbppc/pmppc/pci/pci_machdep.c:1.5 Thu Jun 30 00:52:56 2011
+++ src/sys/arch/evbppc/pmppc/pci/pci_machdep.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.5 2011/06/30 00:52:56 matt Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.6 2016/10/19 00:08:41 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.5 2011/06/30 00:52:56 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.6 2016/10/19 00:08:41 nonaka Exp $");
#include <sys/param.h>
#include <sys/bus.h>
@@ -104,6 +104,16 @@ pmppc_pci_get_chipset_tag(pci_chipset_ta
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = (void *)pc;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = pmppc_pci_conf_interrupt;
pc->pc_decompose_tag = genppc_pci_indirect_decompose_tag;
Index: src/sys/arch/ibmnws/pci/pci_machdep.c
diff -u src/sys/arch/ibmnws/pci/pci_machdep.c:1.9 src/sys/arch/ibmnws/pci/pci_machdep.c:1.10
--- src/sys/arch/ibmnws/pci/pci_machdep.c:1.9 Fri Jul 1 20:47:43 2011
+++ src/sys/arch/ibmnws/pci/pci_machdep.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.9 2011/07/01 20:47:43 dyoung Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.10 2016/10/19 00:08:41 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -79,6 +79,16 @@ ibmnws_pci_get_chipset_tag_indirect(pci_
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = (void *)pc;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = genppc_pci_conf_interrupt;
pc->pc_decompose_tag = genppc_pci_indirect_decompose_tag;
Index: src/sys/arch/macppc/pci/pci_machdep.c
diff -u src/sys/arch/macppc/pci/pci_machdep.c:1.40 src/sys/arch/macppc/pci/pci_machdep.c:1.41
--- src/sys/arch/macppc/pci/pci_machdep.c:1.40 Fri Jul 1 18:43:05 2011
+++ src/sys/arch/macppc/pci/pci_machdep.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.40 2011/07/01 18:43:05 dyoung Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.41 2016/10/19 00:08:41 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.40 2011/07/01 18:43:05 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.41 2016/10/19 00:08:41 nonaka Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -123,6 +123,17 @@ macppc_pci_get_chipset_tag(pci_chipset_t
pc->pc_intr_evcnt = genppc_pci_intr_evcnt;
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
+ pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = (void *)pc;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = genppc_pci_conf_interrupt;
pc->pc_conf_hook = genppc_pci_conf_hook;
Index: src/sys/arch/mvmeppc/pci/pci_machdep.c
diff -u src/sys/arch/mvmeppc/pci/pci_machdep.c:1.10 src/sys/arch/mvmeppc/pci/pci_machdep.c:1.11
--- src/sys/arch/mvmeppc/pci/pci_machdep.c:1.10 Fri Jul 1 20:49:38 2011
+++ src/sys/arch/mvmeppc/pci/pci_machdep.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.10 2011/07/01 20:49:38 dyoung Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.11 2016/10/19 00:08:41 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.10 2011/07/01 20:49:38 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.11 2016/10/19 00:08:41 nonaka Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -88,6 +88,16 @@ mvmeppc_pci_get_chipset_tag(pci_chipset_
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = (void *)pc;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = mvmeppc_pci_conf_interrupt;
pc->pc_decompose_tag = genppc_pci_indirect_decompose_tag;
Index: src/sys/arch/ofppc/pci/ofwpci.c
diff -u src/sys/arch/ofppc/pci/ofwpci.c:1.12 src/sys/arch/ofppc/pci/ofwpci.c:1.13
--- src/sys/arch/ofppc/pci/ofwpci.c:1.12 Fri Feb 28 05:50:27 2014
+++ src/sys/arch/ofppc/pci/ofwpci.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ofwpci.c,v 1.12 2014/02/28 05:50:27 matt Exp $ */
+/* $NetBSD: ofwpci.c,v 1.13 2016/10/19 00:08:41 nonaka Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ofwpci.c,v 1.12 2014/02/28 05:50:27 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ofwpci.c,v 1.13 2016/10/19 00:08:41 nonaka Exp $");
#include "opt_pci.h"
@@ -83,6 +83,17 @@ ofwpci_get_chipset_tag(pci_chipset_tag_t
pc->pc_intr_evcnt = genppc_pci_intr_evcnt;
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
+ pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = (void *)pc;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = genppc_pci_conf_interrupt;
pc->pc_decompose_tag = genppc_pci_ofmethod_decompose_tag;
Index: src/sys/arch/powerpc/booke/e500_intr.c
diff -u src/sys/arch/powerpc/booke/e500_intr.c:1.33 src/sys/arch/powerpc/booke/e500_intr.c:1.34
--- src/sys/arch/powerpc/booke/e500_intr.c:1.33 Tue Apr 14 22:36:54 2015
+++ src/sys/arch/powerpc/booke/e500_intr.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: e500_intr.c,v 1.33 2015/04/14 22:36:54 jmcneill Exp $ */
+/* $NetBSD: e500_intr.c,v 1.34 2016/10/19 00:08:41 nonaka Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -41,7 +41,7 @@
#define __INTR_PRIVATE
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: e500_intr.c,v 1.33 2015/04/14 22:36:54 jmcneill Exp $");
+__KERNEL_RCSID(0, "$NetBSD: e500_intr.c,v 1.34 2016/10/19 00:08:41 nonaka Exp $");
#include <sys/param.h>
#include <sys/proc.h>
@@ -53,6 +53,7 @@ __KERNEL_RCSID(0, "$NetBSD: e500_intr.c,
#include <sys/xcall.h>
#include <sys/ipi.h>
#include <sys/bitops.h>
+#include <sys/interrupt.h>
#include <uvm/uvm_extern.h>
@@ -88,11 +89,14 @@ struct intr_source {
uint8_t is_refcnt;
bus_size_t is_vpr;
bus_size_t is_dr;
+ char is_source[INTRIDBUF];
+ char is_xname[INTRDEVNAMEBUF];
};
#define INTR_SOURCE_INITIALIZER \
{ .is_func = e500_intr_spurious, .is_arg = NULL, \
- .is_irq = -1, .is_ipl = IPL_NONE, .is_ist = IST_NONE, }
+ .is_irq = -1, .is_ipl = IPL_NONE, .is_ist = IST_NONE, \
+ .is_source = "", .is_xname = "", }
struct e500_intr_name {
uint8_t in_irq;
@@ -403,7 +407,8 @@ static const char ist_names[][12] = {
static struct intr_source *e500_intr_sources;
static const struct intr_source *e500_intr_last_source;
-static void *e500_intr_establish(int, int, int, int (*)(void *), void *);
+static void *e500_intr_establish(int, int, int, int (*)(void *), void *,
+ const char *);
static void e500_intr_disestablish(void *);
static void e500_intr_cpu_attach(struct cpu_info *ci);
static void e500_intr_cpu_hatch(struct cpu_info *ci);
@@ -420,6 +425,7 @@ static void e500_wdogintr(struct trapfr
static void e500_spl0(void);
static int e500_splraise(int);
static void e500_splx(int);
+static const char *e500_intr_all_name_lookup(int, int);
const struct intrsw e500_intrsw = {
.intrsw_establish = e500_intr_establish,
@@ -724,7 +730,7 @@ e500_intr_typename(int ist)
static void *
e500_intr_cpu_establish(struct cpu_info *ci, int irq, int ipl, int ist,
- int (*handler)(void *), void *arg)
+ int (*handler)(void *), void *arg, const char *xname)
{
struct cpu_softc * const cpu = ci->ci_softc;
struct e500_intr_irq_info ii;
@@ -738,6 +744,12 @@ e500_intr_cpu_establish(struct cpu_info
return NULL;
}
+ if (xname == NULL) {
+ xname = e500_intr_all_name_lookup(irq, ist);
+ if (xname == NULL)
+ xname = "unknown";
+ }
+
struct intr_source * const is = &e500_intr_sources[ii.irq_vector];
mutex_enter(&e500_intr_lock);
if (is->is_ipl != IPL_NONE) {
@@ -761,6 +773,34 @@ e500_intr_cpu_establish(struct cpu_info
is->is_refcnt++;
is->is_vpr = ii.irq_vpr;
is->is_dr = ii.irq_dr;
+ switch (ist) {
+ case IST_EDGE:
+ case IST_LEVEL_LOW:
+ case IST_LEVEL_HIGH:
+ snprintf(is->is_source, sizeof(is->is_source), "extirq %d",
+ irq);
+ break;
+ case IST_ONCHIP:
+ snprintf(is->is_source, sizeof(is->is_source), "irq %d", irq);
+ break;
+ case IST_MSIGROUP:
+ snprintf(is->is_source, sizeof(is->is_source), "msigroup %d",
+ irq);
+ break;
+ case IST_TIMER:
+ snprintf(is->is_source, sizeof(is->is_source), "timer %d", irq);
+ break;
+ case IST_IPI:
+ snprintf(is->is_source, sizeof(is->is_source), "ipi %d", irq);
+ break;
+ case IST_MI:
+ snprintf(is->is_source, sizeof(is->is_source), "mi %d", irq);
+ break;
+ case IST_PULSE:
+ default:
+ panic("%s: invalid ist (%d)\n", __func__, ist);
+ }
+ strlcpy(is->is_xname, xname, sizeof(is->is_xname));
uint32_t vpr = VPR_PRIORITY_MAKE(IPL2CTPR(ipl))
| VPR_VECTOR_MAKE(((ii.irq_vector + 1) << 4) | ipl)
@@ -801,10 +841,11 @@ e500_intr_cpu_establish(struct cpu_info
}
static void *
-e500_intr_establish(int irq, int ipl, int ist,
- int (*handler)(void *), void *arg)
+e500_intr_establish(int irq, int ipl, int ist, int (*handler)(void *),
+ void *arg, const char *xname)
{
- return e500_intr_cpu_establish(curcpu(), irq, ipl, ist, handler, arg);
+ return e500_intr_cpu_establish(curcpu(), irq, ipl, ist, handler, arg,
+ xname);
}
static void
@@ -1329,6 +1370,7 @@ e500_ipi_intr(void *v)
static void
e500_intr_cpu_hatch(struct cpu_info *ci)
{
+ char iname[INTRIDBUF];
/* Initialize percpu interupts. */
e500_intr_init_precpu();
@@ -1336,15 +1378,16 @@ e500_intr_cpu_hatch(struct cpu_info *ci)
/*
* Establish clock interrupt for this CPU.
*/
+ snprintf(iname, sizeof(iname), "%s clock", device_xname(ci->ci_dev));
if (e500_intr_cpu_establish(ci, E500_CLOCK_TIMER, IPL_CLOCK, IST_TIMER,
- e500_clock_intr, NULL) == NULL)
+ e500_clock_intr, NULL, iname) == NULL)
panic("%s: failed to establish clock interrupt!", __func__);
/*
* Establish the IPI interrupts for this CPU.
*/
if (e500_intr_cpu_establish(ci, 0, IPL_VM, IST_IPI, e500_ipi_intr,
- NULL) == NULL)
+ NULL, "ipi") == NULL)
panic("%s: failed to establish ipi interrupt!", __func__);
/*
@@ -1354,3 +1397,352 @@ e500_intr_cpu_hatch(struct cpu_info *ci)
tcr |= TCR_WIE;
mtspr(SPR_TCR, tcr);
}
+
+static const char *
+e500_intr_all_name_lookup(int irq, int ist)
+{
+ const struct e500_intr_info * const info = &e500_intr_info;
+
+ switch (ist) {
+ default:
+ if (irq < info->ii_external_sources &&
+ (ist == IST_EDGE ||
+ ist == IST_LEVEL_LOW ||
+ ist == IST_LEVEL_HIGH))
+ return e500_intr_name_lookup(
+ info->ii_external_intr_names, irq);
+ break;
+
+ case IST_PULSE:
+ break;
+
+ case IST_ONCHIP:
+ if (irq < info->ii_onchip_sources)
+ return e500_intr_onchip_name_lookup(irq);
+ break;
+
+ case IST_MSIGROUP:
+ if (irq < info->ii_msigroup_sources)
+ return e500_intr_name_lookup(e500_msigroup_intr_names,
+ irq);
+ break;
+
+ case IST_TIMER:
+ if (irq < info->ii_timer_sources)
+ return e500_intr_name_lookup(e500_timer_intr_names,
+ irq);
+ break;
+
+ case IST_IPI:
+ if (irq < info->ii_ipi_sources)
+ return e500_intr_name_lookup(e500_ipi_intr_names, irq);
+ break;
+
+ case IST_MI:
+ if (irq < info->ii_mi_sources)
+ return e500_intr_name_lookup(e500_mi_intr_names, irq);
+ break;
+ }
+
+ return NULL;
+}
+
+static void
+e500_intr_get_affinity(struct intr_source *is, kcpuset_t *cpuset)
+{
+ struct cpu_info * const ci = curcpu();
+ struct cpu_softc * const cpu = ci->ci_softc;
+ struct e500_intr_irq_info ii;
+
+ kcpuset_zero(cpuset);
+
+ if (is->is_ipl != IPL_NONE && !IST_PERCPU_P(is->is_ist)) {
+ if (e500_intr_irq_info_get(ci, is->is_irq, is->is_ipl,
+ is->is_ist, &ii)) {
+ uint32_t dr = openpic_read(cpu, ii.irq_dr);
+ while (dr != 0) {
+ u_int n = ffs(dr);
+ if (n-- == 0)
+ break;
+ dr &= ~(1 << n);
+ kcpuset_set(cpuset, n);
+ }
+ }
+ }
+}
+
+static int
+e500_intr_set_affinity(struct intr_source *is, const kcpuset_t *cpuset)
+{
+ struct cpu_info * const ci = curcpu();
+ struct cpu_softc * const cpu = ci->ci_softc;
+ struct e500_intr_irq_info ii;
+ uint32_t ecpuset, tcpuset;
+
+ KASSERT(mutex_owned(&cpu_lock));
+ KASSERT(mutex_owned(&e500_intr_lock));
+ KASSERT(!kcpuset_iszero(cpuset));
+
+ kcpuset_export_u32(cpuset, &ecpuset, sizeof(ecpuset));
+ tcpuset = ecpuset;
+ while (tcpuset != 0) {
+ u_int cpu_idx = ffs(tcpuset);
+ if (cpu_idx-- == 0)
+ break;
+
+ tcpuset &= ~(1 << cpu_idx);
+ struct cpu_info * const newci = cpu_lookup(cpu_idx);
+ if (newci == NULL)
+ return EINVAL;
+ if ((newci->ci_schedstate.spc_flags & SPCF_NOINTR) != 0)
+ return EINVAL;
+ }
+
+ if (!e500_intr_irq_info_get(ci, is->is_irq, is->is_ipl, is->is_ist,
+ &ii))
+ return ENXIO;
+
+ /*
+ * Update the vector/priority and destination registers keeping the
+ * interrupt masked.
+ */
+ const register_t msr = wrtee(0); /* disable interrupts */
+
+ uint32_t vpr = openpic_read(cpu, ii.irq_vpr);
+ openpic_write(cpu, ii.irq_vpr, vpr | VPR_MSK);
+
+ /*
+ * Wait for the Activity (A) bit for the source to be cleared.
+ */
+ while (openpic_read(cpu, ii.irq_vpr) & VPR_A)
+ continue;
+
+ /*
+ * Update destination register
+ */
+ openpic_write(cpu, ii.irq_dr, ecpuset);
+
+ /*
+ * Now unmask the interrupt.
+ */
+ openpic_write(cpu, ii.irq_vpr, vpr);
+
+ wrtee(msr); /* re-enable interrupts */
+
+ return 0;
+}
+
+static bool
+e500_intr_is_affinity_intrsource(struct intr_source *is,
+ const kcpuset_t *cpuset)
+{
+ struct cpu_info * const ci = curcpu();
+ struct cpu_softc * const cpu = ci->ci_softc;
+ struct e500_intr_irq_info ii;
+ bool result = false;
+
+ if (is->is_ipl != IPL_NONE && !IST_PERCPU_P(is->is_ist)) {
+ if (e500_intr_irq_info_get(ci, is->is_irq, is->is_ipl,
+ is->is_ist, &ii)) {
+ uint32_t dr = openpic_read(cpu, ii.irq_dr);
+ while (dr != 0 && !result) {
+ u_int n = ffs(dr);
+ if (n-- == 0)
+ break;
+ dr &= ~(1 << n);
+ result = kcpuset_isset(cpuset, n);
+ }
+ }
+ }
+ return result;
+}
+
+static struct intr_source *
+e500_intr_get_source(const char *intrid)
+{
+ struct intr_source *is;
+
+ mutex_enter(&e500_intr_lock);
+ for (is = e500_intr_sources; is < e500_intr_last_source; ++is) {
+ if (is->is_source[0] == '\0')
+ continue;
+
+ if (!strncmp(intrid, is->is_source, sizeof(is->is_source) - 1))
+ break;
+ }
+ if (is == e500_intr_last_source)
+ is = NULL;
+ mutex_exit(&e500_intr_lock);
+ return is;
+}
+
+uint64_t
+interrupt_get_count(const char *intrid, u_int cpu_idx)
+{
+ struct cpu_info * const ci = cpu_lookup(cpu_idx);
+ struct cpu_softc * const cpu = ci->ci_softc;
+ struct intr_source *is;
+ struct e500_intr_irq_info ii;
+
+ is = e500_intr_get_source(intrid);
+ if (is == NULL)
+ return 0;
+
+ if (e500_intr_irq_info_get(ci, is->is_irq, is->is_ipl, is->is_ist, &ii))
+ return cpu->cpu_evcnt_intrs[ii.irq_vector].ev_count;
+ return 0;
+}
+
+void
+interrupt_get_assigned(const char *intrid, kcpuset_t *cpuset)
+{
+ struct intr_source *is;
+
+ kcpuset_zero(cpuset);
+
+ is = e500_intr_get_source(intrid);
+ if (is == NULL)
+ return;
+
+ mutex_enter(&e500_intr_lock);
+ e500_intr_get_affinity(is, cpuset);
+ mutex_exit(&e500_intr_lock);
+}
+
+void
+interrupt_get_available(kcpuset_t *cpuset)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+
+ kcpuset_zero(cpuset);
+
+ mutex_enter(&cpu_lock);
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if ((ci->ci_schedstate.spc_flags & SPCF_NOINTR) == 0)
+ kcpuset_set(cpuset, cpu_index(ci));
+ }
+ mutex_exit(&cpu_lock);
+}
+
+void
+interrupt_get_devname(const char *intrid, char *buf, size_t len)
+{
+ struct intr_source *is;
+
+ if (len == 0)
+ return;
+
+ buf[0] = '\0';
+
+ is = e500_intr_get_source(intrid);
+ if (is != NULL)
+ strlcpy(buf, is->is_xname, len);
+}
+
+struct intrids_handler *
+interrupt_construct_intrids(const kcpuset_t *cpuset)
+{
+ struct intr_source *is;
+ struct intrids_handler *ii_handler;
+ intrid_t *ids;
+ int i, n;
+
+ if (kcpuset_iszero(cpuset))
+ return NULL;
+
+ n = 0;
+ mutex_enter(&e500_intr_lock);
+ for (is = e500_intr_sources; is < e500_intr_last_source; ++is) {
+ if (e500_intr_is_affinity_intrsource(is, cpuset))
+ ++n;
+ }
+ mutex_exit(&e500_intr_lock);
+
+ const size_t alloc_size = sizeof(int) + sizeof(intrid_t) * n;
+ ii_handler = kmem_zalloc(alloc_size, KM_SLEEP);
+ if (ii_handler == NULL)
+ return NULL;
+ ii_handler->iih_nids = n;
+ if (n == 0)
+ return ii_handler;
+
+ ids = ii_handler->iih_intrids;
+ mutex_enter(&e500_intr_lock);
+ for (i = 0, is = e500_intr_sources;
+ i < n && is < e500_intr_last_source;
+ ++is) {
+ if (!e500_intr_is_affinity_intrsource(is, cpuset))
+ continue;
+
+ if (is->is_source[0] != '\0') {
+ strlcpy(ids[i], is->is_source, sizeof(ids[0]));
+ ++i;
+ }
+ }
+ mutex_exit(&e500_intr_lock);
+
+ return ii_handler;
+}
+
+void
+interrupt_destruct_intrids(struct intrids_handler *ii_handler)
+{
+ size_t iih_size;
+
+ if (ii_handler == NULL)
+ return;
+
+ iih_size = sizeof(int) + sizeof(intrid_t) * ii_handler->iih_nids;
+ kmem_free(ii_handler, iih_size);
+}
+
+static int
+interrupt_distribute_locked(struct intr_source *is, const kcpuset_t *newset,
+ kcpuset_t *oldset)
+{
+ int error;
+
+ KASSERT(mutex_owned(&cpu_lock));
+
+ if (is->is_ipl == IPL_NONE || IST_PERCPU_P(is->is_ist))
+ return EINVAL;
+
+ mutex_enter(&e500_intr_lock);
+ if (oldset != NULL)
+ e500_intr_get_affinity(is, oldset);
+ error = e500_intr_set_affinity(is, newset);
+ mutex_exit(&e500_intr_lock);
+
+ return error;
+}
+
+int
+interrupt_distribute(void *ich, const kcpuset_t *newset, kcpuset_t *oldset)
+{
+ int error;
+
+ mutex_enter(&cpu_lock);
+ error = interrupt_distribute_locked(ich, newset, oldset);
+ mutex_exit(&cpu_lock);
+
+ return error;
+}
+
+int
+interrupt_distribute_handler(const char *intrid, const kcpuset_t *newset,
+ kcpuset_t *oldset)
+{
+ struct intr_source *is;
+ int error;
+
+ is = e500_intr_get_source(intrid);
+ if (is != NULL) {
+ mutex_enter(&cpu_lock);
+ error = interrupt_distribute_locked(is, newset, oldset);
+ mutex_exit(&cpu_lock);
+ } else
+ error = ENOENT;
+
+ return error;
+}
Index: src/sys/arch/powerpc/booke/pci/pq3pci.c
diff -u src/sys/arch/powerpc/booke/pci/pq3pci.c:1.21 src/sys/arch/powerpc/booke/pci/pq3pci.c:1.22
--- src/sys/arch/powerpc/booke/pci/pq3pci.c:1.21 Fri Oct 2 05:22:51 2015
+++ src/sys/arch/powerpc/booke/pci/pq3pci.c Wed Oct 19 00:08:41 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pq3pci.c,v 1.21 2015/10/02 05:22:51 msaitoh Exp $ */
+/* $NetBSD: pq3pci.c,v 1.22 2016/10/19 00:08:41 nonaka Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -44,7 +44,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.21 2015/10/02 05:22:51 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1.22 2016/10/19 00:08:41 nonaka Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -55,6 +55,7 @@ __KERNEL_RCSID(0, "$NetBSD: pq3pci.c,v 1
#include <sys/bitops.h>
#include <sys/kmem.h>
#include <sys/malloc.h> /* for extent */
+#include <sys/once.h>
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
@@ -254,8 +255,9 @@ struct pq3pci_intrsource {
SIMPLEQ_HEAD(,pq3pci_intrhand) pis_ihands;
struct evcnt pis_ev;
struct evcnt pis_ev_spurious;
- kmutex_t *pis_lock;
+ kmutex_t pis_lock;
pci_intr_handle_t pis_handle;
+ char pis_intrname[PCI_INTRSTR_LEN];
void *pis_ih;
};
@@ -269,7 +271,7 @@ struct pq3pci_msihand {
};
struct pq3pci_msigroup {
- kmutex_t *msig_lock;
+ kmutex_t msig_lock;
void *msig_ih;
uint32_t msig_free_mask;
int msig_ipl;
@@ -299,12 +301,15 @@ static int pq3pci_cpunode_match(device_t
static void pq3pci_cpunode_attach(device_t, device_t, void *aux);
static pci_chipset_tag_t pq3pci_pci_chipset_init(struct pq3pci_softc *);
+static ONCE_DECL(pq3pci_init_once);
+static kmutex_t pq3pci_intrsources_lock;
+static kmutex_t pq3pci_msigroups_lock;
static SIMPLEQ_HEAD(,pq3pci_intrsource) pq3pci_intrsources
= SIMPLEQ_HEAD_INITIALIZER(pq3pci_intrsources);
static struct pq3pci_msigroup *pq3pci_msigroups[8];
static struct pq3pci_intrsource *
- pq3pci_intr_source_lookup(struct pq3pci_softc *, pci_intr_handle_t);
+ pq3pci_intr_source_lookup(struct pq3pci_softc *, pci_intr_handle_t);
static const char msi_intr_names[8][32][8] = {
{
@@ -557,17 +562,6 @@ pq3pci_iwin_setup(struct pq3pci_softc *s
return true;
}
-static void
-pq3pci_pch_callout(void *v)
-{
- struct pq3pci_callhand * const pch = v;
-
- int s = splraise(pch->pch_ipl);
- (*pch->pch_ih.ih_func)(pch->pch_ih.ih_arg);
- splx(s);
- callout_schedule(&pch->pch_callout, 1);
-}
-
static int
pq3pci_msi_spurious_intr(void *v)
{
@@ -581,14 +575,14 @@ pq3pci_msi_intr(void *v)
{
struct pq3pci_msigroup * const msig = v;
- mutex_spin_enter(msig->msig_lock);
+ mutex_spin_enter(&msig->msig_lock);
KASSERT(curcpu()->ci_cpl == msig->msig_ipl);
//KASSERT(curcpu()->ci_idepth == 0);
uint32_t matches = 0;
for (int rv = 0;;) {
uint32_t group = cpu_read_4(msig->msig_msir);
if (group == 0) {
- mutex_spin_exit(msig->msig_lock);
+ mutex_spin_exit(&msig->msig_lock);
return rv;
}
@@ -653,7 +647,7 @@ pq3pci_pis_intr(void *v)
struct pq3pci_intrhand *pih;
int rv = 0;
- mutex_spin_enter(pis->pis_lock);
+ mutex_spin_enter(&pis->pis_lock);
pis->pis_ev.ev_count++;
SIMPLEQ_FOREACH(pih, &pis->pis_ihands, pih_link) {
struct pq3pci_softc * const sc = pih->pih_ih.ih_sc;
@@ -675,26 +669,27 @@ pq3pci_pis_intr(void *v)
}
if (rv == 0)
pis->pis_ev_spurious.ev_count++;
- mutex_spin_exit(pis->pis_lock);
+ mutex_spin_exit(&pis->pis_lock);
return rv;
}
static void
-pq3pci_intr_source_setup(struct pq3pci_softc *sc,
- struct pq3pci_intrsource *pis, pci_intr_handle_t handle)
+pq3pci_intr_source_setup(struct pq3pci_softc *sc, struct pq3pci_intrsource *pis,
+ pci_intr_handle_t handle)
{
- char buf[PCI_INTRSTR_LEN];
SIMPLEQ_INIT(&pis->pis_ihands);
pis->pis_handle = handle;
pis->pis_ih = intr_establish(PIH_IRQ(handle), IPL_VM, PIH_IST(handle),
pq3pci_pis_intr, pis);
- pis->pis_lock = mutex_obj_alloc(MUTEX_DEFAULT, IPL_VM);
+ mutex_init(&pis->pis_lock, MUTEX_DEFAULT, IPL_VM);
const char * const intrstr
- = intr_string(PIH_IRQ(handle), PIH_IST(handle), buf, sizeof(buf));
- evcnt_attach_dynamic(&pis->pis_ev, EVCNT_TYPE_INTR,
- NULL, intrstr, "intr");
+ = intr_string(PIH_IRQ(handle), PIH_IST(handle), pis->pis_intrname,
+ sizeof(pis->pis_intrname));
+ evcnt_attach_dynamic(&pis->pis_ev, EVCNT_TYPE_INTR, NULL, intrstr,
+ "intr");
evcnt_attach_dynamic(&pis->pis_ev_spurious, EVCNT_TYPE_INTR,
&pis->pis_ev, intrstr, "spurious intr");
+ KASSERT(mutex_owned(&pq3pci_intrsources_lock));
SIMPLEQ_INSERT_TAIL(&pq3pci_intrsources, pis, pis_link);
}
@@ -717,8 +712,8 @@ pq3pci_intrmap_setup(struct pq3pci_softc
sc->sc_intrmask = prop_number_unsigned_integer_value(pn);
- sc->sc_ih = intr_establish(cnl->cnl_intrs[0], IPL_VM, IST_ONCHIP,
- pq3pci_onchip_intr, sc);
+ sc->sc_ih = intr_establish_xname(cnl->cnl_intrs[0], IPL_VM, IST_ONCHIP,
+ pq3pci_onchip_intr, sc, device_xname(sc->sc_dev));
if (sc->sc_ih == NULL)
panic("%s: failed to establish interrupt %d\n",
device_xname(sc->sc_dev), cnl->cnl_intrs[0]);
@@ -726,6 +721,16 @@ pq3pci_intrmap_setup(struct pq3pci_softc
return true;
}
+static int
+pq3pci_once_init(void)
+{
+
+ mutex_init(&pq3pci_intrsources_lock, MUTEX_DEFAULT, IPL_VM);
+ mutex_init(&pq3pci_msigroups_lock, MUTEX_DEFAULT, IPL_VM);
+
+ return 0;
+}
+
void
pq3pci_cpunode_attach(device_t parent, device_t self, void *aux)
{
@@ -740,6 +745,8 @@ pq3pci_cpunode_attach(device_t parent, d
psc->sc_children |= cna->cna_childmask;
sc->sc_pcie = strcmp(cnl->cnl_name, "pcie") == 0;
+ RUN_ONCE(&pq3pci_init_once, pq3pci_once_init);
+
const uint32_t pordevsr = cpu_read_4(GLOBAL_BASE + PORDEVSR);
if (sc->sc_pcie) {
u_int lanes = e500_truth_decode(cnl->cnl_instance, pordevsr,
@@ -1118,6 +1125,7 @@ pq3pci_conf_write(void *v, pcitag_t tag,
mutex_spin_exit(sc->sc_conf_lock);
}
+#ifdef PCI_NETBSD_CONFIGURE
static int
pq3pci_conf_hook(void *v, int bus, int dev, int func, pcireg_t id)
{
@@ -1132,21 +1140,24 @@ pq3pci_conf_hook(void *v, int bus, int d
}
return PCI_CONF_DEFAULT;
}
+#endif
static void
pq3pci_msi_group_setup(struct pq3pci_msigroup *msig, u_int group, int ipl)
{
+ char buf[12];
const char (*intr_names)[8] = msi_intr_names[group];
KASSERT(ipl == IPL_VM);
+ KASSERT(mutex_owned(&pq3pci_msigroups_lock));
- pq3pci_msigroups[group] = msig;
msig->msig_group = group;
msig->msig_free_mask = ~0 << (group == 0);
msig->msig_ipl = ipl;
- msig->msig_lock = mutex_obj_alloc(MUTEX_DEFAULT, ipl);
- msig->msig_ih = intr_establish(msig->msig_group, ipl, IST_MSIGROUP,
- pq3pci_msi_intr, msig);
+ mutex_init(&msig->msig_lock, MUTEX_DEFAULT, ipl);
+ snprintf(buf, sizeof(buf), "msi %d-%d", group * 32, group * 32 + 31);
+ msig->msig_ih = intr_establish_xname(msig->msig_group, ipl,
+ IST_MSIGROUP, pq3pci_msi_intr, msig, buf);
msig->msig_msir = OPENPIC_BASE + OPENPIC_MSIR(msig->msig_group);
for (u_int i = 0; i < __arraycount(msig->msig_ihands); i++) {
struct pq3pci_msihand * const msih = msig->msig_ihands + i;
@@ -1159,16 +1170,44 @@ pq3pci_msi_group_setup(struct pq3pci_msi
evcnt_attach_dynamic(&msih->msih_ev_spurious, EVCNT_TYPE_INTR,
&msih->msih_ev, intr_names[i], "spurious intr");
}
+ pq3pci_msigroups[group] = msig;
+}
+
+static struct pq3pci_msihand *
+pq3pci_msi_lookup(pci_intr_handle_t handle)
+{
+ const int irq = PIH_IRQ(handle);
+ KASSERT(irq < 256);
+ struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
+ KASSERT(msig != NULL);
+ return &msig->msig_ihands[irq & 31];
+}
+
+static struct pq3pci_msihand *
+pq3pci_msi_claim(pci_intr_handle_t handle)
+{
+ const int irq = PIH_IRQ(handle);
+ uint32_t irq_mask = __BIT(irq & 31);
+ KASSERT(irq < 256);
+ struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
+ KASSERT(msig != NULL);
+ struct pq3pci_msihand * const msih = &msig->msig_ihands[irq & 31];
+ mutex_spin_enter(&msig->msig_lock);
+ KASSERT(msig->msig_free_mask & irq_mask);
+ msig->msig_free_mask ^= irq_mask;
+ mutex_spin_exit(&msig->msig_lock);
+ return msih;
}
static pci_intr_handle_t
-pq3pci_msi_alloc(int ipl, u_int rmsi)
+pq3pci_msi_alloc_one(int ipl)
{
size_t freegroup = 0;
- size_t maplen = __arraycount(pq3pci_msigroups);
- KASSERT(rmsi <= 5);
+ const size_t maplen = __arraycount(pq3pci_msigroups);
uint32_t bitmap[maplen];
+ pci_intr_handle_t handle;
+ mutex_spin_enter(&pq3pci_msigroups_lock);
for (u_int i = 0; i < maplen; i++) {
struct pq3pci_msigroup * const msig = pq3pci_msigroups[i];
if (msig == NULL) {
@@ -1192,57 +1231,113 @@ pq3pci_msi_alloc(int ipl, u_int rmsi)
uint32_t mapbits = bitmap[i];
u_int n = ffs(mapbits);
if (n--) {
- return PIH_MAKE(i * 32 + n, IST_MSI, 0);
+ handle = PIH_MAKE(i * 32 + n, IST_MSI, 0);
+ struct pq3pci_msihand * const msih __diagused =
+ pq3pci_msi_claim(handle);
+ KASSERT(msih != NULL);
+ mutex_spin_exit(&pq3pci_msigroups_lock);
+ return handle;
}
}
- if (freegroup-- == 0)
+ if (freegroup-- == 0) {
+ mutex_spin_exit(&pq3pci_msigroups_lock);
return 0;
+ }
struct pq3pci_msigroup * const msig =
- kmem_zalloc(sizeof(*msig), KM_SLEEP);
- KASSERT(msig != NULL);
+ kmem_zalloc(sizeof(*msig), KM_NOSLEEP);
+ if (msig == NULL) {
+ mutex_spin_exit(&pq3pci_msigroups_lock);
+ return 0;
+ }
pq3pci_msi_group_setup(msig, freegroup, ipl);
u_int n = ffs(msig->msig_free_mask) - 1;
- return PIH_MAKE(freegroup * 32 + n, IST_MSI, 0);
+ handle = PIH_MAKE(freegroup * 32 + n, IST_MSI, 0);
+ struct pq3pci_msihand * const msih __diagused =
+ pq3pci_msi_claim(handle);
+ KASSERT(msih != NULL);
+ mutex_spin_exit(&pq3pci_msigroups_lock);
+ return handle;
}
-static struct pq3pci_msihand *
-pq3pci_msi_lookup(pci_intr_handle_t handle)
+static int
+pq3pci_msi_alloc_vectors(struct pq3pci_softc *sc,
+ const struct pci_attach_args *pa, pci_intr_handle_t **ihps, int count)
{
- const int irq = PIH_IRQ(handle);
- KASSERT(irq < 256);
- struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
- KASSERT(msig != NULL);
- return &msig->msig_ihands[irq & 31];
+ pci_intr_handle_t *vectors;
+ struct pq3pci_msihand * msih;
+ pcireg_t msictl;
+ int msioff;
+
+ *ihps = NULL;
+
+ if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI, &msioff,
+ NULL))
+ return ENODEV;
+
+ msictl = pci_conf_read(pa->pa_pc, pa->pa_tag, msioff);
+ msictl &= ~PCI_MSI_CTL_MSI_ENABLE;
+ msictl &= ~PCI_MSI_CTL_MME_MASK;
+ pci_conf_write(pa->pa_pc, pa->pa_tag, msioff, msictl);
+
+ const size_t alloc_size = sizeof(*vectors) * count;
+ vectors = kmem_zalloc(alloc_size, KM_SLEEP);
+ if (vectors == NULL)
+ return ENOMEM;
+
+ for (int i = 0; i < count; ++i) {
+ pci_intr_handle_t handle = pq3pci_msi_alloc_one(IPL_VM);
+ if (handle == 0) {
+ for (int j = i - 1; j >= 0; j--) {
+ msih = pq3pci_msi_claim(vectors[j]);
+ msih->msih_tag = 0;
+ msih->msih_msioff = 0;
+ }
+ kmem_free(vectors, alloc_size);
+ return EBUSY;
+ }
+ vectors[i] = handle;
+
+ msih = pq3pci_msi_lookup(handle);
+ msih->msih_tag = pa->pa_tag;
+ msih->msih_msioff = msioff;
+ }
+
+ *ihps = vectors;
+ return 0;
}
-static struct pq3pci_msihand *
-pq3pci_msi_claim(pci_intr_handle_t handle)
+static void
+pq3pci_msi_free_vectors(struct pq3pci_softc *sc, pci_intr_handle_t *ihp,
+ int count)
{
- const int irq = PIH_IRQ(handle);
- uint32_t irq_mask = __BIT(irq & 31);
- KASSERT(irq < 256);
- struct pq3pci_msigroup * const msig = pq3pci_msigroups[irq / 32];
- KASSERT(msig != NULL);
- struct pq3pci_msihand * const msih = &msig->msig_ihands[irq & 31];
- mutex_spin_enter(msig->msig_lock);
- KASSERT(msig->msig_free_mask & irq_mask);
- msig->msig_free_mask ^= irq_mask;
- mutex_spin_exit(msig->msig_lock);
- return msih;
+
+ KASSERT(count > 0);
+
+ for (int i = 0; i < count; ++i) {
+ struct pq3pci_msihand * const msih __diagused =
+ pq3pci_msi_claim(ihp[i]);
+ KASSERT(msih != NULL);
+ }
+ kmem_free(ihp, sizeof(*ihp) * count);
}
static struct pq3pci_intrsource *
pq3pci_intr_source_lookup(struct pq3pci_softc *sc, pci_intr_handle_t handle)
{
struct pq3pci_intrsource *pis;
+ mutex_spin_enter(&pq3pci_intrsources_lock);
SIMPLEQ_FOREACH(pis, &pq3pci_intrsources, pis_link) {
- if (pis->pis_handle == handle)
+ if (pis->pis_handle == handle) {
+ mutex_spin_exit(&pq3pci_intrsources_lock);
return pis;
+ }
}
- pis = kmem_zalloc(sizeof(*pis), KM_SLEEP);
- pq3pci_intr_source_setup(sc, pis, handle);
+ pis = kmem_zalloc(sizeof(*pis), KM_NOSLEEP);
+ if (pis != NULL)
+ pq3pci_intr_source_setup(sc, pis, handle);
+ mutex_spin_exit(&pq3pci_intrsources_lock);
return pis;
}
@@ -1252,24 +1347,24 @@ pq3pci_intr_handle_lookup(struct pq3pci_
{
prop_dictionary_t entry;
+#ifndef PQ3PCI_INTR_MAP_NO_USE_MSI
if (sc->sc_pcie) do {
pcireg_t msictl;
int msioff;
if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_MSI,
- &msioff, &msictl))
+ &msioff, NULL))
break;
msictl = pci_conf_read(pa->pa_pc, pa->pa_tag, msioff);
msictl &= ~PCI_MSI_CTL_MSI_ENABLE;
msictl &= ~PCI_MSI_CTL_MME_MASK;
- int rmsi = __SHIFTOUT(msictl, PCI_MSI_CTL_MMC_MASK);
pci_conf_write(pa->pa_pc, pa->pa_tag, msioff, msictl);
- pci_intr_handle_t handle = pq3pci_msi_alloc(IPL_VM, rmsi);
+ pci_intr_handle_t handle = pq3pci_msi_alloc_one(IPL_VM);
struct pq3pci_msihand * const msih = pq3pci_msi_lookup(handle);
msih->msih_tag = pa->pa_tag;
msih->msih_msioff = msioff;
return handle;
} while (false);
-
+#endif
if (sc->sc_intrmask == 0) {
entry = prop_dictionary_get(sc->sc_intrmap, "000000");
@@ -1333,40 +1428,30 @@ static const struct evcnt *
pq3pci_intr_evcnt(void *v, pci_intr_handle_t handle)
{
struct pq3pci_softc * const sc = v;
- struct pq3pci_intrsource * const pis =
- pq3pci_intr_source_lookup(sc, handle);
+ if (PIH_IST(handle) == IST_MSI) {
+ struct pq3pci_msihand * const msih = pq3pci_msi_lookup(handle);
- KASSERT(pis != NULL);
+ KASSERT(msih != NULL);
- return &pis->pis_ev;
+ return &msih->msih_ev;
+ }
+ struct pq3pci_intrsource * const pis =
+ pq3pci_intr_source_lookup(sc, handle);
+ if (pis != NULL)
+ return &pis->pis_ev;
+ return NULL;
}
static void *
pq3pci_intr_establish(void *v, pci_intr_handle_t handle, int ipl,
- int (*func)(void *), void *arg)
+ int (*func)(void *), void *arg, const char *xname)
{
struct pq3pci_softc * const sc = v;
-
- if (0) {
- struct pq3pci_callhand * const pch =
- kmem_zalloc(sizeof(*pch), KM_SLEEP);
- KASSERT(pch);
- pch->pch_ih.ih_arg = arg;
- pch->pch_ih.ih_func = func;
- pch->pch_ih.ih_sc = sc;
- pch->pch_ipl = ipl;
-
- callout_init(&pch->pch_callout, 0);
- callout_reset(&pch->pch_callout, 1, pq3pci_pch_callout, pch);
-
- return pch;
- }
-
const int ist = PIH_IST(handle);
if (ist == IST_MSI) {
pci_chipset_tag_t pc = &sc->sc_pc;
- struct pq3pci_msihand * const msih = pq3pci_msi_claim(handle);
+ struct pq3pci_msihand * const msih = pq3pci_msi_lookup(handle);
pcireg_t cmdsts, msictl;
if (msih == NULL)
@@ -1375,7 +1460,7 @@ pq3pci_intr_establish(void *v, pci_intr_
struct pq3pci_msigroup * const msig = msih->msih_group;
const pcitag_t tag = msih->msih_tag;
- mutex_spin_enter(msig->msig_lock);
+ mutex_spin_enter(&msig->msig_lock);
msih->msih_ih.ih_class = IH_MSI;
msih->msih_ih.ih_arg = arg;
msih->msih_ih.ih_func = func;
@@ -1416,7 +1501,7 @@ pq3pci_intr_establish(void *v, pci_intr_
off += 4;
pci_conf_write(pc, tag, off, 0);
}
-
+
/*
* Let's make sure he won't raise any INTx. Technically
* setting MSI enable will prevent that as well but might
@@ -1434,55 +1519,34 @@ pq3pci_intr_establish(void *v, pci_intr_
pci_conf_write(pc, tag, msih->msih_msioff, msictl);
#endif
- mutex_spin_exit(msig->msig_lock);
-
-#if 0
- struct pq3pci_callhand * const pch =
- kmem_zalloc(sizeof(*pch), KM_SLEEP);
- KASSERT(pch);
-
- pch->pch_ih.ih_arg = msig;
- pch->pch_ih.ih_func = pq3pci_msi_intr;
-#if 1
- pch->pch_ih.ih_arg = arg;
- pch->pch_ih.ih_func = func;
-#endif
- pch->pch_ih.ih_sc = sc;
- pch->pch_ipl = ipl;
-
- callout_init(&pch->pch_callout, 0);
- callout_reset(&pch->pch_callout, 1, pq3pci_pch_callout, pch);
-
-#if 1
- return pch;
-#endif
-#endif
+ mutex_spin_exit(&msig->msig_lock);
return msih;
- } else {
- struct pq3pci_intrsource * const pis =
- pq3pci_intr_source_lookup(sc, handle);
- KASSERT(pis != NULL);
+ }
+
+ struct pq3pci_intrsource * const pis =
+ pq3pci_intr_source_lookup(sc, handle);
+ if (pis == NULL)
+ return NULL;
- struct pq3pci_intrhand * const pih =
- kmem_zalloc(sizeof(*pih), KM_SLEEP);
+ struct pq3pci_intrhand * const pih =
+ kmem_zalloc(sizeof(*pih), KM_SLEEP);
- if (pih == NULL)
- return NULL;
+ if (pih == NULL)
+ return NULL;
- pih->pih_ih.ih_class = IH_INTX;
- pih->pih_ih.ih_func = func;
- pih->pih_ih.ih_arg = arg;
- pih->pih_ih.ih_sc = sc;
- pih->pih_ipl = ipl;
- pih->pih_source = pis;
-
- mutex_spin_enter(pis->pis_lock);
- SIMPLEQ_INSERT_TAIL(&pis->pis_ihands, pih, pih_link);
- mutex_spin_exit(pis->pis_lock);
+ pih->pih_ih.ih_class = IH_INTX;
+ pih->pih_ih.ih_func = func;
+ pih->pih_ih.ih_arg = arg;
+ pih->pih_ih.ih_sc = sc;
+ pih->pih_ipl = ipl;
+ pih->pih_source = pis;
+
+ mutex_spin_enter(&pis->pis_lock);
+ SIMPLEQ_INSERT_TAIL(&pis->pis_ihands, pih, pih_link);
+ mutex_spin_exit(&pis->pis_lock);
- return pih;
- }
+ return pih;
}
static void
@@ -1494,19 +1558,20 @@ pq3pci_intr_disestablish(void *v, void *
struct pq3pci_intrhand * const pih = ih;
struct pq3pci_intrsource * const pis = pih->pih_source;
- mutex_spin_enter(pis->pis_lock);
+ mutex_spin_enter(&pis->pis_lock);
SIMPLEQ_REMOVE(&pis->pis_ihands, pih, pq3pci_intrhand, pih_link);
- mutex_spin_exit(pis->pis_lock);
+ mutex_spin_exit(&pis->pis_lock);
kmem_free(pih, sizeof(*pih));
return;
}
+
struct pq3pci_msihand * const msih = ih;
struct pq3pci_msigroup * const msig = msih->msih_group;
struct genppc_pci_chipset * const pc = &msih->msih_ih.ih_sc->sc_pc;
const pcitag_t tag = msih->msih_tag;
- mutex_spin_enter(msig->msig_lock);
+ mutex_spin_enter(&msig->msig_lock);
/*
* disable the MSI
@@ -1520,7 +1585,102 @@ pq3pci_intr_disestablish(void *v, void *
msih->msih_ih.ih_sc = NULL;
msih->msih_tag = 0;
msih->msih_msioff = 0;
- mutex_spin_exit(msig->msig_lock);
+ mutex_spin_exit(&msig->msig_lock);
+}
+
+static pci_intr_type_t
+pq3pci_intr_type(void *v, pci_intr_handle_t handle)
+{
+ const int ist = PIH_IST(handle);
+
+ if (ist == IST_MSI)
+ return PCI_INTR_TYPE_MSI;
+ return PCI_INTR_TYPE_INTX;
+}
+
+static int
+pq3pci_intr_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *counts, pci_intr_type_t max_type)
+{
+ int cnt[PCI_INTR_TYPE_SIZE];
+ int error;
+
+ memset(cnt, 0, sizeof(cnt));
+ if (counts == NULL) {
+ /* simple pattern */
+ cnt[PCI_INTR_TYPE_INTX] = 1;
+ cnt[PCI_INTR_TYPE_MSI] = 1;
+ } else {
+ switch (max_type) {
+ case PCI_INTR_TYPE_MSIX:
+ cnt[PCI_INTR_TYPE_MSIX] = counts[PCI_INTR_TYPE_MSIX];
+ /*FALLTHROUGH*/
+ case PCI_INTR_TYPE_MSI:
+ cnt[PCI_INTR_TYPE_MSI] = counts[PCI_INTR_TYPE_MSI];
+ /*FALLTHROUGH*/
+ case PCI_INTR_TYPE_INTX:
+ cnt[PCI_INTR_TYPE_INTX] = counts[PCI_INTR_TYPE_INTX];
+ break;
+ default:
+ return EINVAL;
+ }
+ }
+
+ if (counts != NULL)
+ memset(counts, 0, sizeof(counts[0]) * (max_type + 1));
+ error = EINVAL;
+
+ /* try MSI-X */
+ if (cnt[PCI_INTR_TYPE_MSIX] == -1) /* use hardware max */
+ cnt[PCI_INTR_TYPE_MSIX] = pci_msix_count(pa->pa_pc, pa->pa_tag);
+ if (cnt[PCI_INTR_TYPE_MSIX] > 0) {
+ error = pci_msix_alloc_exact(pa, ihps, cnt[PCI_INTR_TYPE_MSIX]);
+ if (error == 0) {
+ KASSERTMSG(counts != NULL,
+ "If MSI-X is used, counts must not be NULL.");
+ counts[PCI_INTR_TYPE_MSIX] = cnt[PCI_INTR_TYPE_MSIX];
+ goto out;
+ }
+ }
+
+ /* try MSI */
+ if (cnt[PCI_INTR_TYPE_MSI] == -1) /* use hardware max */
+ cnt[PCI_INTR_TYPE_MSI] = pci_msi_count(pa->pa_pc, pa->pa_tag);
+ if (cnt[PCI_INTR_TYPE_MSI] > 0) {
+ error = pci_msi_alloc_exact(pa, ihps, cnt[PCI_INTR_TYPE_MSI]);
+ if (error == 0) {
+ if (counts != NULL) {
+ counts[PCI_INTR_TYPE_MSI] =
+ cnt[PCI_INTR_TYPE_MSI];
+ }
+ goto out;
+ }
+ }
+
+ /* try INTx */
+ if (cnt[PCI_INTR_TYPE_INTX] > 0) {
+ error = pci_intx_alloc(pa, ihps);
+ if (error == 0 && counts != NULL) {
+ counts[PCI_INTR_TYPE_INTX] = 1;
+ }
+ }
+
+ out:
+ return error;
+}
+
+static void
+pq3pci_intr_release(void *v, pci_intr_handle_t *ihps, int count)
+{
+
+ if (ihps == NULL)
+ return;
+
+ const int ist = PIH_IST(*ihps);
+ if (ist == IST_MSI)
+ pq3pci_msi_free_vectors(v, ihps, count);
+ else
+ genppc_pci_intr_release(v, ihps, count);
}
static void
@@ -1528,6 +1688,50 @@ pq3pci_conf_interrupt(void *v, int bus,
{
}
+/* experimental MSI support */
+
+/*
+ * This function is used by device drivers like pci_intr_map().
+ *
+ * "ihps" is the array of vector numbers which MSI used instead of IRQ number.
+ * "count" must be powr of 2.
+ * "count" can decrease if sturct intrsource cannot be allocated.
+ * if count == 0, return non-zero value.
+ */
+static int
+pq3pci_msi_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count, bool exact)
+{
+ struct pq3pci_softc * const sc = pa->pa_pc->pc_msi_v;
+ int hw_max;
+ int error;
+
+ if (*count < 1)
+ return EINVAL;
+ if (((*count - 1) & *count) != 0)
+ return EINVAL;
+
+ hw_max = pci_msi_count(pa->pa_pc, pa->pa_tag);
+ if (hw_max == 0)
+ return ENODEV;
+
+ if (*count > hw_max)
+ *count = hw_max;
+
+ *ihps = NULL;
+ for (; *count > 0; (*count) >>= 1) {
+ error = pq3pci_msi_alloc_vectors(sc, pa, ihps, *count);
+ if (error == 0)
+ break;
+ if (exact)
+ return error;
+ }
+ if (*ihps == NULL)
+ return ENXIO;
+
+ return 0;
+}
+
static pci_chipset_tag_t
pq3pci_pci_chipset_init(struct pq3pci_softc *sc)
{
@@ -1535,48 +1739,42 @@ pq3pci_pci_chipset_init(struct pq3pci_so
pc->pc_conf_v = sc;
pc->pc_attach_hook = pq3pci_attach_hook;
- pc->pc_bus_maxdevs = pq3pci_bus_maxdevs;
- pc->pc_make_tag = pq3pci_make_tag;
- pc->pc_conf_read = pq3pci_conf_read;
- pc->pc_conf_write = pq3pci_conf_write;
+ pc->pc_bus_maxdevs = pq3pci_bus_maxdevs;
+ pc->pc_make_tag = pq3pci_make_tag;
+ pc->pc_conf_read = pq3pci_conf_read;
+ pc->pc_conf_write = pq3pci_conf_write;
#ifdef PCI_NETBSD_CONFIGURE
- pc->pc_conf_hook = pq3pci_conf_hook;
+ pc->pc_conf_hook = pq3pci_conf_hook;
#endif
- pc->pc_intr_v = sc;
- pc->pc_intr_map = pq3pci_intr_map;
- pc->pc_intr_string = pq3pci_intr_string;
- pc->pc_intr_evcnt = pq3pci_intr_evcnt;
- pc->pc_intr_establish = pq3pci_intr_establish;
- pc->pc_intr_disestablish = pq3pci_intr_disestablish;
- pc->pc_conf_interrupt = pq3pci_conf_interrupt;
+ pc->pc_intr_v = sc;
+ pc->pc_intr_map = pq3pci_intr_map;
+ pc->pc_intr_string = pq3pci_intr_string;
+ pc->pc_intr_evcnt = pq3pci_intr_evcnt;
+ pc->pc_intr_establish = pq3pci_intr_establish;
+ pc->pc_intr_disestablish = pq3pci_intr_disestablish;
+ pc->pc_intr_type = pq3pci_intr_type;
+ pc->pc_intr_alloc = pq3pci_intr_alloc;
+ pc->pc_intr_release = pq3pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
pc->pc_msi_v = sc;
- genppc_pci_chipset_msi_init(pc);
-#if 0
- pc->pc_msi_request = pq3pci_msi_request;
- pc->pc_msi_available = pq3pci_msi_available;
- pc->pc_msi_type = pq3pci_msi_type;
- pc->pc_msi_string = pq3pci_msi_string;
- pc->pc_msi_evcnt = genppc_pci_msi_evcnt;
- pc->pc_msi_establish = pq3pci_msi_establish;
- pc->pc_msix_establish = pq3pci_msix_establish;
- pc->pc_msi_disestablish = pq3pci_msi_disestablish;
- pc->pc_msi_release = pq3pci_msi_release;
- pc->pc_msi_free = pq3pci_msi_free;
-#endif
+ pc->pc_msi_alloc = pq3pci_msi_alloc;
+
+ pc->pc_msix_v = sc;
+ genppc_pci_chipset_msix_init(pc);
- pc->pc_decompose_tag = pq3pci_decompose_tag;
- pc->pc_conf_hook = pq3pci_conf_hook;
+ pc->pc_conf_interrupt = pq3pci_conf_interrupt;
+ pc->pc_decompose_tag = pq3pci_decompose_tag;
/*
* This is a horrible kludge but it makes life easier.
*/
- pc->pc_addr = (void *)(sc->sc_bsh + PEX_CONFIG_ADDR);
- pc->pc_data = (void *)(sc->sc_bsh + PEX_CONFIG_DATA);
- pc->pc_bus = 0;
- pc->pc_memt = &sc->sc_pci_mem_bst.bs_tag;
- pc->pc_iot = &sc->sc_pci_io_bst.bs_tag;
+ pc->pc_addr = (void *)(sc->sc_bsh + PEX_CONFIG_ADDR);
+ pc->pc_data = (void *)(sc->sc_bsh + PEX_CONFIG_DATA);
+ pc->pc_bus = 0;
+ pc->pc_memt = &sc->sc_pci_mem_bst.bs_tag;
+ pc->pc_iot = &sc->sc_pci_io_bst.bs_tag;
SIMPLEQ_INIT(&pc->pc_pbi);
Index: src/sys/arch/powerpc/ibm4xx/dev/ibm405gp.c
diff -u src/sys/arch/powerpc/ibm4xx/dev/ibm405gp.c:1.7 src/sys/arch/powerpc/ibm4xx/dev/ibm405gp.c:1.8
--- src/sys/arch/powerpc/ibm4xx/dev/ibm405gp.c:1.7 Wed Aug 17 18:52:01 2011
+++ src/sys/arch/powerpc/ibm4xx/dev/ibm405gp.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: ibm405gp.c,v 1.7 2011/08/17 18:52:01 matt Exp $ */
+/* $NetBSD: ibm405gp.c,v 1.8 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright 2001 Wasabi Systems, Inc.
@@ -36,7 +36,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: ibm405gp.c,v 1.7 2011/08/17 18:52:01 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: ibm405gp.c,v 1.8 2016/10/19 00:08:42 nonaka Exp $");
#include <sys/param.h>
#include <sys/device.h>
@@ -76,10 +76,17 @@ static struct genppc_pci_chipset genppc_
.pc_intr_establish = genppc_pci_intr_establish,
.pc_intr_disestablish = genppc_pci_intr_disestablish,
.pc_intr_setattr = ibm4xx_pci_intr_setattr,
+ .pc_intr_type = genppc_pci_intr_type,
+ .pc_intr_alloc = genppc_pci_intr_alloc,
+ .pc_intr_release = genppc_pci_intr_release,
+ .pc_intx_alloc = genppc_pci_intx_alloc,
.pc_msi_v = &genppc_ibm4xx_chipset,
GENPPC_PCI_MSI_INITIALIZER,
+ .pc_msix_v = &genppc_ibm4xx_chipset,
+ GENPPC_PCI_MSIX_INITIALIZER,
+
.pc_conf_interrupt = ibm4xx_pci_conf_interrupt,
.pc_decompose_tag = ibm4xx_pci_decompose_tag,
.pc_conf_hook = ibm4xx_pci_conf_hook,
Index: src/sys/arch/powerpc/include/cpu.h
diff -u src/sys/arch/powerpc/include/cpu.h:1.101 src/sys/arch/powerpc/include/cpu.h:1.102
--- src/sys/arch/powerpc/include/cpu.h:1.101 Fri Jan 23 07:27:05 2015
+++ src/sys/arch/powerpc/include/cpu.h Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: cpu.h,v 1.101 2015/01/23 07:27:05 nonaka Exp $ */
+/* $NetBSD: cpu.h,v 1.102 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright (C) 1999 Wolfgang Solfrank.
@@ -51,7 +51,7 @@ struct cache_info {
#endif
#ifdef _KERNEL
-#include <machine/intr.h>
+#include <sys/intr.h>
#include <sys/device_if.h>
#include <sys/evcnt.h>
#endif
Index: src/sys/arch/powerpc/include/intr.h
diff -u src/sys/arch/powerpc/include/intr.h:1.11 src/sys/arch/powerpc/include/intr.h:1.12
--- src/sys/arch/powerpc/include/intr.h:1.11 Fri Aug 23 06:18:14 2013
+++ src/sys/arch/powerpc/include/intr.h Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.11 2013/08/23 06:18:14 matt Exp $ */
+/* $NetBSD: intr.h,v 1.12 2016/10/19 00:08:42 nonaka Exp $ */
/*-
* Copyright (c) 2007 Michael Lorenz
@@ -28,7 +28,7 @@
#ifndef _LOCORE
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.h,v 1.11 2013/08/23 06:18:14 matt Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.h,v 1.12 2016/10/19 00:08:42 nonaka Exp $");
#endif
#ifndef _POWERPC_INTR_MACHDEP_H_
@@ -61,6 +61,8 @@ __KERNEL_RCSID(0, "$NetBSD: intr.h,v 1.1
#if !defined(_LOCORE)
void * intr_establish(int, int, int, int (*)(void *), void *);
+void * intr_establish_xname(int, int, int, int (*)(void *), void *,
+ const char *);
void intr_disestablish(void *);
const char *
intr_typename(int);
@@ -85,6 +87,7 @@ struct intrhand {
struct intrhand *ih_next;
int ih_ipl;
int ih_virq;
+ char ih_xname[INTRDEVNAMEBUF];
};
void softint_fast_dispatch(struct lwp *, int);
Index: src/sys/arch/powerpc/include/pci_machdep.h
diff -u src/sys/arch/powerpc/include/pci_machdep.h:1.13 src/sys/arch/powerpc/include/pci_machdep.h:1.14
--- src/sys/arch/powerpc/include/pci_machdep.h:1.13 Sat Mar 29 19:28:29 2014
+++ src/sys/arch/powerpc/include/pci_machdep.h Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.h,v 1.13 2014/03/29 19:28:29 christos Exp $ */
+/* $NetBSD: pci_machdep.h,v 1.14 2016/10/19 00:08:42 nonaka Exp $ */
/*-
* Copyright (c) 2002,2007 The NetBSD Foundation, Inc.
@@ -39,12 +39,12 @@
*/
#define __HAVE_PCI_CONF_HOOK
+#define __HAVE_PCI_MSI_MSIX
/*
* Types provided to machine-independent PCI code
*/
typedef struct genppc_pci_chipset *pci_chipset_tag_t;
-typedef void *pci_msi_handle_t;
typedef int pcitag_t;
typedef int pci_intr_handle_t;
@@ -63,6 +63,13 @@ static inline pci_chipset_tag_t pci_atta
#ifdef _KERNEL
extern struct powerpc_bus_dma_tag pci_bus_dma_tag;
+
+typedef enum {
+ PCI_INTR_TYPE_INTX = 0,
+ PCI_INTR_TYPE_MSI,
+ PCI_INTR_TYPE_MSIX,
+ PCI_INTR_TYPE_SIZE,
+} pci_intr_type_t;
#endif
@@ -83,26 +90,34 @@ const struct evcnt *
pci_intr_evcnt(pci_chipset_tag_t, pci_intr_handle_t);
void * pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
int, int (*)(void *), void *);
+void * pci_intr_establish_xname(pci_chipset_tag_t, pci_intr_handle_t,
+ int, int (*)(void *), void *, const char *);
void pci_intr_disestablish(pci_chipset_tag_t, void *);
int pci_intr_map(const struct pci_attach_args *,
pci_intr_handle_t *ihp);
int pci_intr_setattr(pci_chipset_tag_t, pci_intr_handle_t *,
int, uint64_t);
-int pci_msi_request(const struct pci_attach_args *,
- pci_msi_handle_t *, size_t, int, int);
-int pci_msi_type(pci_chipset_tag_t, pci_msi_handle_t);
-size_t pci_msi_available(pci_chipset_tag_t, pci_msi_handle_t);
-const char * pci_msi_string(pci_chipset_tag_t, pci_msi_handle_t, size_t);
-const struct evcnt *
- pci_msi_evcnt(pci_chipset_tag_t, pci_msi_handle_t, size_t);
-void * pci_msi_establish(pci_chipset_tag_t, pci_msi_handle_t, size_t,
- int, int (*)(void *), void *);
-void * pci_msix_establish(pci_chipset_tag_t, pci_msi_handle_t, size_t,
- size_t, int, int (*)(void *), void *);
-void pci_msi_disestablish(pci_chipset_tag_t, void *);
-void pci_msi_free(pci_chipset_tag_t, pci_msi_handle_t, size_t);
-void pci_msi_release(pci_chipset_tag_t, pci_msi_handle_t);
+pci_intr_type_t pci_intr_type(pci_chipset_tag_t, pci_intr_handle_t);
+int pci_intr_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *, pci_intr_type_t);
+void pci_intr_release(pci_chipset_tag_t, pci_intr_handle_t *, int);
+int pci_intx_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **);
+
+/* experimental MSI support */
+int pci_msi_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *);
+int pci_msi_alloc_exact(const struct pci_attach_args *,
+ pci_intr_handle_t **, int);
+
+/* experimental MSI-X support */
+int pci_msix_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *);
+int pci_msix_alloc_exact(const struct pci_attach_args *,
+ pci_intr_handle_t **, int);
+int pci_msix_alloc_map(const struct pci_attach_args *,
+ pci_intr_handle_t **, u_int *, int);
void pci_conf_interrupt(pci_chipset_tag_t, int, int, int,
int, int *);
@@ -136,26 +151,27 @@ struct genppc_pci_chipset {
size_t);
const struct evcnt *(*pc_intr_evcnt)(void *, pci_intr_handle_t);
void *(*pc_intr_establish)(void *, pci_intr_handle_t,
- int, int (*)(void *), void *);
+ int, int (*)(void *), void *, const char *);
void (*pc_intr_disestablish)(void *, void *);
int (*pc_intr_setattr)(void *, pci_intr_handle_t *,
int, uint64_t);
+ pci_intr_type_t (*pc_intr_type)(void *, pci_intr_handle_t);
+ int (*pc_intr_alloc)(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *, pci_intr_type_t);
+ void (*pc_intr_release)(void *, pci_intr_handle_t *, int);
+ int (*pc_intx_alloc)(const struct pci_attach_args *,
+ pci_intr_handle_t **);
+
+ /* experimental MSI support */
void *pc_msi_v;
- int (*pc_msi_request)(const struct pci_attach_args *,
- pci_msi_handle_t *, size_t, int, int);
- int (*pc_msi_type)(void *, pci_msi_handle_t);
- size_t (*pc_msi_available)(void *, pci_msi_handle_t);
- const char * (*pc_msi_string)(void *, pci_msi_handle_t, size_t);
- const struct evcnt *
- (*pc_msi_evcnt)(void *, pci_msi_handle_t, size_t);
- void * (*pc_msi_establish)(void *, pci_msi_handle_t, size_t,
- int, int (*)(void *), void *);
- void * (*pc_msix_establish)(void *, pci_msi_handle_t, size_t,
- size_t, int, int (*)(void *), void *);
- void (*pc_msi_disestablish)(void *, void *);
- void (*pc_msi_free)(void *, pci_msi_handle_t, size_t);
- void (*pc_msi_release)(void *, pci_msi_handle_t);
+ int (*pc_msi_alloc)(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *, bool);
+
+ /* experimental MSI-X support */
+ void *pc_msix_v;
+ int (*pc_msix_alloc)(const struct pci_attach_args *,
+ pci_intr_handle_t **, u_int *, int *, bool);
void (*pc_conf_interrupt)(void *, int, int, int, int, int *);
void (*pc_decompose_tag)(void *, pcitag_t, int *,
@@ -243,7 +259,16 @@ __pci_inline void *
pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int ipl,
int (*handler)(void *), void *arg)
{
- return (*pc->pc_intr_establish)(pc->pc_intr_v, ih, ipl, handler, arg);
+ return (*pc->pc_intr_establish)(pc->pc_intr_v, ih, ipl, handler, arg,
+ NULL);
+}
+
+__pci_inline void *
+pci_intr_establish_xname(pci_chipset_tag_t pc, pci_intr_handle_t ih, int ipl,
+ int (*handler)(void *), void *arg, const char *xname)
+{
+ return (*pc->pc_intr_establish)(pc->pc_intr_v, ih, ipl, handler, arg,
+ xname);
}
__pci_inline void
@@ -259,85 +284,89 @@ pci_intr_setattr(pci_chipset_tag_t pc, p
return (*pc->pc_intr_setattr)(pc->pc_intr_v, ihp, attr, data);
}
-
-__pci_inline void
-pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int device, int pin,
- int swiz, int *iline)
+__pci_inline pci_intr_type_t
+pci_intr_type(pci_chipset_tag_t pc, pci_intr_handle_t ih)
{
- (*pc->pc_conf_interrupt)(pc->pc_conf_v, bus, device, pin, swiz, iline);
+ return (*pc->pc_intr_type)(pc->pc_intr_v, ih);
}
__pci_inline int
-pci_conf_hook(pci_chipset_tag_t pc, int bus, int device, int function,
- pcireg_t id)
+pci_intr_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count, pci_intr_type_t max_type)
{
- return (*pc->pc_conf_hook)(pc->pc_conf_v, bus, device, function, id);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_intr_alloc)(pa, ihps, count, max_type);
}
-__pci_inline int
-pci_msi_request(const struct pci_attach_args *pa, pci_msi_handle_t *msihp,
- size_t nmsi, int ipl, int capid)
+__pci_inline void
+pci_intr_release(pci_chipset_tag_t pc, pci_intr_handle_t *ihp, int count)
{
- return (*pci_attach_args_pc(pa)->pc_msi_request)(pa, msihp, nmsi,
- ipl, capid);
+ (*pc->pc_intr_release)(pc->pc_intr_v, ihp, count);
}
__pci_inline int
-pci_msi_type(pci_chipset_tag_t pc, pci_msi_handle_t msih)
+pci_intx_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps)
{
- return (*pc->pc_msi_type)(pc->pc_msi_v, msih);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_intx_alloc)(pa, ihps);
}
-__pci_inline size_t
-pci_msi_available(pci_chipset_tag_t pc, pci_msi_handle_t msih)
-{
- return (*pc->pc_msi_available)(pc->pc_msi_v, msih);
-}
-__pci_inline const char *
-pci_msi_string(pci_chipset_tag_t pc, pci_msi_handle_t msih, size_t msirq)
+__pci_inline void
+pci_conf_interrupt(pci_chipset_tag_t pc, int bus, int device, int pin,
+ int swiz, int *iline)
{
- return (*pc->pc_msi_string)(pc->pc_msi_v, msih, msirq);
+ (*pc->pc_conf_interrupt)(pc->pc_conf_v, bus, device, pin, swiz, iline);
}
-__pci_inline const struct evcnt *
-pci_msi_evcnt(pci_chipset_tag_t pc, pci_msi_handle_t msih, size_t msirq)
+__pci_inline int
+pci_conf_hook(pci_chipset_tag_t pc, int bus, int device, int function,
+ pcireg_t id)
{
- return (*pc->pc_msi_evcnt)(pc->pc_msi_v, msih, msirq);
+ return (*pc->pc_conf_hook)(pc->pc_conf_v, bus, device, function, id);
}
-__pci_inline void *
-pci_msi_establish(pci_chipset_tag_t pc, pci_msi_handle_t msih, size_t msirq,
- int ipl, int (*func)(void *), void *arg)
+
+/* experimental MSI support */
+__pci_inline int
+pci_msi_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count)
{
- return (*pc->pc_msi_establish)(pc->pc_msi_v, msih, msirq, ipl,
- func, arg);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_msi_alloc)(pa, ihps, count, false);
}
-__pci_inline void *
-pci_msix_establish(pci_chipset_tag_t pc, pci_msi_handle_t msih, size_t vec,
- size_t msirq, int ipl, int (*func)(void *), void *arg)
+__pci_inline int
+pci_msi_alloc_exact(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int count)
{
- return (*pc->pc_msix_establish)(pc->pc_msi_v, msih, vec, msirq, ipl,
- func, arg);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_msi_alloc)(pa, ihps, &count, true);
}
-__pci_inline void
-pci_msi_disestablish(pci_chipset_tag_t pc, void *ih)
+/* experimental MSI-X support */
+__pci_inline int
+pci_msix_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count)
{
- (*pc->pc_msi_disestablish)(pc->pc_msi_v, ih);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_msix_alloc)(pa, ihps, NULL, count, false);
}
-__pci_inline void
-pci_msi_free(pci_chipset_tag_t pc, pci_msi_handle_t msih, size_t msirq)
+__pci_inline int
+pci_msix_alloc_exact(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int count)
{
- (*pc->pc_msi_free)(pc->pc_msi_v, msih, msirq);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_msix_alloc)(pa, ihps, NULL, &count, true);
}
-__pci_inline void
-pci_msi_release(pci_chipset_tag_t pc, pci_msi_handle_t msih)
+__pci_inline int
+pci_msix_alloc_map(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ u_int *table_indexes, int count)
{
- (*pc->pc_msi_release)(pc->pc_msi_v, msih);
+ pci_chipset_tag_t pc = pci_attach_args_pc(pa);
+ return (*pc->pc_msix_alloc)(pa, ihps, table_indexes, &count, true);
}
#undef __pci_inline
@@ -353,36 +382,31 @@ int genppc_pci_intr_map(const struct pci
const char *genppc_pci_intr_string(void *, pci_intr_handle_t, char *, size_t);
const struct evcnt *genppc_pci_intr_evcnt(void *, pci_intr_handle_t);
void *genppc_pci_intr_establish(void *, pci_intr_handle_t, int, int (*)(void *),
- void *);
+ void *, const char *);
void genppc_pci_intr_disestablish(void *, void *);
int genppc_pci_intr_setattr(void *, pci_intr_handle_t *, int, uint64_t);
+pci_intr_type_t genppc_pci_intr_type(void *, pci_intr_handle_t);
+int genppc_pci_intr_alloc(const struct pci_attach_args *, pci_intr_handle_t **,
+ int *, pci_intr_type_t);
+void genppc_pci_intr_release(void *, pci_intr_handle_t *, int);
+int genppc_pci_intx_alloc(const struct pci_attach_args *, pci_intr_handle_t **);
+
+/* experimental MSI support */
+int genppc_pci_msi_alloc(const struct pci_attach_args *, pci_intr_handle_t **,
+ int *, bool);
+
+/* experimental MSI-X support */
+int genppc_pci_msix_alloc(const struct pci_attach_args *, pci_intr_handle_t **,
+ u_int *, int *, bool);
-int genppc_pci_msi_request(const struct pci_attach_args *, pci_msi_handle_t *,
- size_t, int, int);
-int genppc_pci_msi_type(void *, pci_msi_handle_t);
-size_t genppc_pci_msi_available(void *, pci_msi_handle_t);
-const struct evcnt *genppc_pci_msi_evcnt(void *, pci_msi_handle_t, size_t);
-const char *genppc_pci_msi_string(void *, pci_msi_handle_t, size_t);
-void *genppc_pci_msi_establish(void *, pci_msi_handle_t, size_t,
- int, int (*)(void *), void *);
-void *genppc_pci_msix_establish(void *, pci_msi_handle_t, size_t,
- size_t, int, int (*)(void *), void *);
-void genppc_pci_msi_disestablish(void *, void *);
-void genppc_pci_msi_free(void *, pci_msi_handle_t, size_t);
-void genppc_pci_msi_release(void *, pci_msi_handle_t);
-void genppc_pci_chipset_msi_init(pci_chipset_tag_t);
+void genppc_pci_chipset_msi_init(pci_chipset_tag_t pc);
+void genppc_pci_chipset_msix_init(pci_chipset_tag_t pc);
#define GENPPC_PCI_MSI_INITIALIZER \
- .pc_msi_request = genppc_pci_msi_request, \
- .pc_msi_type = genppc_pci_msi_type, \
- .pc_msi_available = genppc_pci_msi_available, \
- .pc_msi_evcnt = genppc_pci_msi_evcnt, \
- .pc_msi_string = genppc_pci_msi_string, \
- .pc_msi_establish = genppc_pci_msi_establish, \
- .pc_msix_establish = genppc_pci_msix_establish, \
- .pc_msi_disestablish = genppc_pci_msi_disestablish, \
- .pc_msi_free = genppc_pci_msi_free, \
- .pc_msi_release = genppc_pci_msi_release
+ .pc_msi_alloc = genppc_pci_msi_alloc
+
+#define GENPPC_PCI_MSIX_INITIALIZER \
+ .pc_msix_alloc = genppc_pci_msix_alloc
void genppc_pci_conf_interrupt(void *, int, int, int, int, int *);
int genppc_pci_conf_hook(void *, int, int, int, pcireg_t);
Index: src/sys/arch/powerpc/include/booke/intr.h
diff -u src/sys/arch/powerpc/include/booke/intr.h:1.9 src/sys/arch/powerpc/include/booke/intr.h:1.10
--- src/sys/arch/powerpc/include/booke/intr.h:1.9 Fri Jan 23 07:27:05 2015
+++ src/sys/arch/powerpc/include/booke/intr.h Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.h,v 1.9 2015/01/23 07:27:05 nonaka Exp $ */
+/* $NetBSD: intr.h,v 1.10 2016/10/19 00:08:42 nonaka Exp $ */
/*-
* Copyright (c) 2010, 2011 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -84,6 +84,8 @@
struct cpu_info;
void *intr_establish(int, int, int, int (*)(void *), void *);
+void *intr_establish_xname(int, int, int, int (*)(void *), void *,
+ const char *);
void intr_disestablish(void *);
void intr_cpu_attach(struct cpu_info *);
void intr_cpu_hatch(struct cpu_info *);
@@ -118,7 +120,8 @@ typedef struct {
struct trapframe;
struct intrsw {
- void *(*intrsw_establish)(int, int, int, int (*)(void *), void *);
+ void *(*intrsw_establish)(int, int, int, int (*)(void *), void *,
+ const char *);
void (*intrsw_disestablish)(void *);
void (*intrsw_cpu_attach)(struct cpu_info *);
void (*intrsw_cpu_hatch)(struct cpu_info *);
Index: src/sys/arch/powerpc/marvell/pci_machdep.c
diff -u src/sys/arch/powerpc/marvell/pci_machdep.c:1.5 src/sys/arch/powerpc/marvell/pci_machdep.c:1.6
--- src/sys/arch/powerpc/marvell/pci_machdep.c:1.5 Fri Jul 5 02:18:37 2013
+++ src/sys/arch/powerpc/marvell/pci_machdep.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.5 2013/07/05 02:18:37 joerg Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.6 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright (c) 2009 KIYOHARA Takashi
* All rights reserved.
@@ -26,7 +26,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.5 2013/07/05 02:18:37 joerg Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.6 2016/10/19 00:08:42 nonaka Exp $");
#include "gtpci.h"
#include "pci.h"
@@ -51,7 +51,6 @@ __KERNEL_RCSID(0, "$NetBSD: pci_machdep.
void gtpci_md_conf_interrupt(void *, int, int, int, int, int *);
int gtpci_md_conf_hook(void *, int, int, int, pcireg_t);
-
struct genppc_pci_chipset genppc_gtpci0_chipset = {
.pc_conf_v = NULL,
.pc_attach_hook = gtpci_attach_hook,
@@ -67,14 +66,22 @@ struct genppc_pci_chipset genppc_gtpci0_
.pc_intr_establish = genppc_pci_intr_establish,
.pc_intr_disestablish = genppc_pci_intr_disestablish,
.pc_intr_setattr = genppc_pci_intr_setattr,
+ .pc_intr_type = genppc_pci_intr_type,
+ .pc_intr_alloc = genppc_pci_intr_alloc,
+ .pc_intr_release = genppc_pci_intr_release,
+ .pc_intx_alloc = genppc_pci_intx_alloc,
.pc_msi_v = &genppc_gtpci0_chipset,
GENPPC_PCI_MSI_INITIALIZER,
+ .pc_msix_v = &genppc_gtpci0_chipset,
+ GENPPC_PCI_MSIX_INITIALIZER,
+
.pc_conf_interrupt = gtpci_md_conf_interrupt,
.pc_decompose_tag = gtpci_decompose_tag,
.pc_conf_hook = gtpci_md_conf_hook,
};
+
struct genppc_pci_chipset genppc_gtpci1_chipset = {
.pc_conf_v = NULL,
.pc_attach_hook = gtpci_attach_hook,
@@ -90,10 +97,17 @@ struct genppc_pci_chipset genppc_gtpci1_
.pc_intr_establish = genppc_pci_intr_establish,
.pc_intr_disestablish = genppc_pci_intr_disestablish,
.pc_intr_setattr = genppc_pci_intr_setattr,
+ .pc_intr_type = genppc_pci_intr_type,
+ .pc_intr_alloc = genppc_pci_intr_alloc,
+ .pc_intr_release = genppc_pci_intr_release,
+ .pc_intx_alloc = genppc_pci_intx_alloc,
.pc_msi_v = &genppc_gtpci1_chipset,
GENPPC_PCI_MSI_INITIALIZER,
+ .pc_msix_v = &genppc_gtpci1_chipset,
+ GENPPC_PCI_MSIX_INITIALIZER,
+
.pc_conf_interrupt = gtpci_md_conf_interrupt,
.pc_decompose_tag = gtpci_decompose_tag,
.pc_conf_hook = gtpci_md_conf_hook,
Index: src/sys/arch/powerpc/pci/pci_machdep_common.c
diff -u src/sys/arch/powerpc/pci/pci_machdep_common.c:1.20 src/sys/arch/powerpc/pci/pci_machdep_common.c:1.21
--- src/sys/arch/powerpc/pci/pci_machdep_common.c:1.20 Sat Mar 29 19:28:29 2014
+++ src/sys/arch/powerpc/pci/pci_machdep_common.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep_common.c,v 1.20 2014/03/29 19:28:29 christos Exp $ */
+/* $NetBSD: pci_machdep_common.c,v 1.21 2016/10/19 00:08:42 nonaka Exp $ */
/*-
* Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep_common.c,v 1.20 2014/03/29 19:28:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep_common.c,v 1.21 2016/10/19 00:08:42 nonaka Exp $");
#define _POWERPC_BUS_DMA_PRIVATE
@@ -47,6 +47,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_machdep_
#include <sys/errno.h>
#include <sys/extent.h>
#include <sys/intr.h>
+#include <sys/kmem.h>
#include <sys/systm.h>
#include <sys/time.h>
@@ -112,7 +113,7 @@ genppc_pci_intr_evcnt(void *v, pci_intr_
void *
genppc_pci_intr_establish(void *v, pci_intr_handle_t ih, int level,
- int (*func)(void *), void *arg)
+ int (*func)(void *), void *arg, const char *xname)
{
#ifdef ICU_LEN
@@ -124,7 +125,7 @@ genppc_pci_intr_establish(void *v, pci_i
panic("pci_intr_establish: bogus handle 0x%x", ih);
#endif
- return intr_establish(ih, IST_LEVEL, level, func, arg);
+ return intr_establish_xname(ih, IST_LEVEL, level, func, arg, xname);
}
void
@@ -142,6 +143,67 @@ genppc_pci_intr_setattr(void *v, pci_int
return ENODEV;
}
+pci_intr_type_t
+genppc_pci_intr_type(void *v, pci_intr_handle_t ih)
+{
+
+ return PCI_INTR_TYPE_INTX;
+}
+
+int
+genppc_pci_intr_alloc(const struct pci_attach_args *pa,
+ pci_intr_handle_t **ihps, int *counts, pci_intr_type_t max_type)
+{
+ pci_intr_handle_t *ihp;
+
+ if (counts != NULL && counts[PCI_INTR_TYPE_INTX] == 0)
+ return EINVAL;
+
+ ihp = kmem_alloc(sizeof(*ihp), KM_SLEEP);
+ if (ihp == NULL)
+ return ENOMEM;
+
+ if (pci_intr_map(pa, ihp)) {
+ kmem_free(ihp, sizeof(*ihp));
+ return EINVAL;
+ }
+
+ *ihps = ihp;
+ return 0;
+}
+
+void
+genppc_pci_intr_release(void *v, pci_intr_handle_t *pih, int count)
+{
+
+ if (pih == NULL)
+ return;
+
+ KASSERT(count == 1);
+ kmem_free(pih, sizeof(*pih));
+}
+
+int
+genppc_pci_intx_alloc(const struct pci_attach_args *pa,
+ pci_intr_handle_t **ihps)
+{
+ pci_intr_handle_t *handle;
+ int error;
+
+ handle = kmem_zalloc(sizeof(*handle), KM_SLEEP);
+ if (handle == NULL)
+ return ENOMEM;
+
+ error = pci_intr_map(pa, handle);
+ if (error != 0) {
+ kmem_free(handle, sizeof(*handle));
+ return error;
+ }
+
+ *ihps = handle;
+ return 0;
+}
+
void
genppc_pci_conf_interrupt(void *v, int bus, int dev, int pin,
int swiz, int *iline)
@@ -210,82 +272,34 @@ bad:
return 1;
}
+/* experimental MSI support */
int
-genppc_pci_msi_request(const struct pci_attach_args *pa,
- pci_msi_handle_t *msihp, size_t nmsirq, int ipl, int capid)
+genppc_pci_msi_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count, bool exact)
{
+
return EOPNOTSUPP;
}
+/* experimental MSI-X support */
int
-genppc_pci_msi_type(void *v, pci_msi_handle_t msih)
+genppc_pci_msix_alloc(const struct pci_attach_args *pa,
+ pci_intr_handle_t **ihps, u_int *table_indexes, int *count, bool exact)
{
- panic("%s", __func__);
-}
-
-size_t
-genppc_pci_msi_available(void *v, pci_msi_handle_t msih)
-{
- panic("%s", __func__);
-}
-
-const char *
-genppc_pci_msi_string(void *v, pci_msi_handle_t msih, size_t msirq)
-{
- panic("%s", __func__);
-}
-const struct evcnt *
-genppc_pci_msi_evcnt(void *v, pci_msi_handle_t msih, size_t msirq)
-{
- panic("%s", __func__);
-}
-
-void *
-genppc_pci_msi_establish(void *v, pci_msi_handle_t msih, size_t msirq,
- int ipl, int (*func)(void *), void *arg)
-{
- panic("%s", __func__);
-}
-
-void *
-genppc_pci_msix_establish(void *v, pci_msi_handle_t msih, size_t vec,
- size_t msirq, int ipl, int (*func)(void *), void *arg)
-{
- panic("%s", __func__);
-}
-
-void
-genppc_pci_msi_disestablish(void *v, void *ih)
-{
- panic("%s", __func__);
-}
-
-void
-genppc_pci_msi_free(void *v, pci_msi_handle_t msih, size_t msirq)
-{
- panic("%s", __func__);
+ return EOPNOTSUPP;
}
void
-genppc_pci_msi_release(void *v, pci_msi_handle_t msih)
+genppc_pci_chipset_msi_init(pci_chipset_tag_t pc)
{
- panic("%s", __func__);
+ pc->pc_msi_alloc = genppc_pci_msi_alloc;
}
void
-genppc_pci_chipset_msi_init(pci_chipset_tag_t pc)
+genppc_pci_chipset_msix_init(pci_chipset_tag_t pc)
{
- pc->pc_msi_request = genppc_pci_msi_request;
- pc->pc_msi_type = genppc_pci_msi_type;
- pc->pc_msi_available = genppc_pci_msi_available;
- pc->pc_msi_evcnt = genppc_pci_msi_evcnt;
- pc->pc_msi_string = genppc_pci_msi_string;
- pc->pc_msi_establish = genppc_pci_msi_establish;
- pc->pc_msix_establish = genppc_pci_msix_establish;
- pc->pc_msi_disestablish = genppc_pci_msi_disestablish;
- pc->pc_msi_free = genppc_pci_msi_free;
- pc->pc_msi_release = genppc_pci_msi_release;
+ pc->pc_msix_alloc = genppc_pci_msix_alloc;
}
#ifdef __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
Index: src/sys/arch/powerpc/pic/intr.c
diff -u src/sys/arch/powerpc/pic/intr.c:1.24 src/sys/arch/powerpc/pic/intr.c:1.25
--- src/sys/arch/powerpc/pic/intr.c:1.24 Thu May 26 17:38:05 2016
+++ src/sys/arch/powerpc/pic/intr.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: intr.c,v 1.24 2016/05/26 17:38:05 macallan Exp $ */
+/* $NetBSD: intr.c,v 1.25 2016/10/19 00:08:42 nonaka Exp $ */
/*-
* Copyright (c) 2007 Michael Lorenz
@@ -27,7 +27,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.24 2016/05/26 17:38:05 macallan Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.25 2016/10/19 00:08:42 nonaka Exp $");
#include "opt_interrupt.h"
#include "opt_multiprocessor.h"
@@ -39,6 +39,7 @@ __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.2
#include <sys/cpu.h>
#include <sys/kernel.h>
#include <sys/kmem.h>
+#include <sys/interrupt.h>
#include <powerpc/psl.h>
#include <powerpc/pic/picvar.h>
@@ -132,6 +133,13 @@ void *
intr_establish(int hwirq, int type, int ipl, int (*ih_fun)(void *),
void *ih_arg)
{
+ return intr_establish_xname(hwirq, type, ipl, ih_fun, ih_arg, NULL);
+}
+
+void *
+intr_establish_xname(int hwirq, int type, int ipl, int (*ih_fun)(void *),
+ void *ih_arg, const char *xname)
+{
struct intrhand **p, *q, *ih;
struct pic_ops *pic;
static struct intrhand fakehand;
@@ -147,7 +155,6 @@ intr_establish(int hwirq, int type, int
pic = find_pic_by_hwirq(hwirq);
if (pic == NULL) {
-
panic("%s: cannot find a pic for IRQ %d", __func__, hwirq);
}
@@ -215,6 +222,8 @@ intr_establish(int hwirq, int type, int
ih->ih_next = NULL;
ih->ih_ipl = ipl;
ih->ih_virq = virq;
+ strlcpy(ih->ih_xname, xname != NULL ? xname : "unknown",
+ sizeof(ih->ih_xname));
*p = ih;
if (pic->pic_establish_irq != NULL)
@@ -232,7 +241,6 @@ intr_establish(int hwirq, int type, int
*/
intr_calculatemasks();
-
return ih;
}
@@ -718,3 +726,156 @@ genppc_isa_intr_alloc(isa_chipset_tag_t
return 1;
}
#endif
+
+static struct intr_source *
+intr_get_source(const char *intrid)
+{
+ struct intr_source *is;
+ int irq;
+
+ for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) {
+ if (strcmp(intrid, is->is_source) == 0)
+ return is;
+ }
+ return NULL;
+}
+
+static struct intrhand *
+intr_get_handler(const char *intrid)
+{
+ struct intr_source *is;
+
+ is = intr_get_source(intrid);
+ if (is != NULL)
+ return is->is_hand;
+ return NULL;
+}
+
+uint64_t
+interrupt_get_count(const char *intrid, u_int cpu_idx)
+{
+ struct intr_source *is;
+
+ /* XXX interrupt is always generated by CPU 0 */
+ if (cpu_idx != 0)
+ return 0;
+
+ is = intr_get_source(intrid);
+ if (is != NULL)
+ return is->is_ev.ev_count;
+ return 0;
+}
+
+void
+interrupt_get_assigned(const char *intrid, kcpuset_t *cpuset)
+{
+ struct intr_source *is;
+
+ kcpuset_zero(cpuset);
+
+ is = intr_get_source(intrid);
+ if (is != NULL)
+ kcpuset_set(cpuset, 0); /* XXX */
+}
+
+void
+interrupt_get_available(kcpuset_t *cpuset)
+{
+ CPU_INFO_ITERATOR cii;
+ struct cpu_info *ci;
+
+ kcpuset_zero(cpuset);
+
+ mutex_enter(&cpu_lock);
+ for (CPU_INFO_FOREACH(cii, ci)) {
+ if ((ci->ci_schedstate.spc_flags & SPCF_NOINTR) == 0)
+ kcpuset_set(cpuset, cpu_index(ci));
+ }
+ mutex_exit(&cpu_lock);
+}
+
+void
+interrupt_get_devname(const char *intrid, char *buf, size_t len)
+{
+ struct intrhand *ih;
+
+ if (len == 0)
+ return;
+
+ buf[0] = '\0';
+
+ for (ih = intr_get_handler(intrid); ih != NULL; ih = ih->ih_next) {
+ if (buf[0] != '\0')
+ strlcat(buf, ", ", len);
+ strlcat(buf, ih->ih_xname, len);
+ }
+}
+
+struct intrids_handler *
+interrupt_construct_intrids(const kcpuset_t *cpuset)
+{
+ struct intr_source *is;
+ struct intrids_handler *ii_handler;
+ intrid_t *ids;
+ int i, irq, count;
+
+ if (kcpuset_iszero(cpuset))
+ return NULL;
+ if (!kcpuset_isset(cpuset, 0)) /* XXX */
+ return NULL;
+
+ count = 0;
+ for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) {
+ if (is->is_hand != NULL)
+ count++;
+ }
+
+ ii_handler = kmem_zalloc(sizeof(int) + sizeof(intrid_t) * count,
+ KM_SLEEP);
+ if (ii_handler == NULL)
+ return NULL;
+ ii_handler->iih_nids = count;
+ if (count == 0)
+ return ii_handler;
+
+ ids = ii_handler->iih_intrids;
+ i = 0;
+ for (irq = 0, is = intrsources; irq < NVIRQ; irq++, is++) {
+ /* Ignore devices attached after counting "count". */
+ if (i >= count)
+ break;
+
+ if (is->is_hand == NULL)
+ continue;
+
+ strncpy(ids[i], is->is_source, sizeof(intrid_t));
+ i++;
+ }
+
+ return ii_handler;
+}
+
+void
+interrupt_destruct_intrids(struct intrids_handler *ii_handler)
+{
+ size_t iih_size;
+
+ if (ii_handler == NULL)
+ return;
+
+ iih_size = sizeof(int) + sizeof(intrid_t) * ii_handler->iih_nids;
+ kmem_free(ii_handler, iih_size);
+}
+
+int
+interrupt_distribute(void *ich, const kcpuset_t *newset, kcpuset_t *oldset)
+{
+ return EOPNOTSUPP;
+}
+
+int
+interrupt_distribute_handler(const char *intrid, const kcpuset_t *newset,
+ kcpuset_t *oldset)
+{
+ return EOPNOTSUPP;
+}
Index: src/sys/arch/powerpc/powerpc/intr_stubs.c
diff -u src/sys/arch/powerpc/powerpc/intr_stubs.c:1.4 src/sys/arch/powerpc/powerpc/intr_stubs.c:1.5
--- src/sys/arch/powerpc/powerpc/intr_stubs.c:1.4 Sat Mar 29 19:28:29 2014
+++ src/sys/arch/powerpc/powerpc/intr_stubs.c Wed Oct 19 00:08:42 2016
@@ -38,7 +38,7 @@
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr_stubs.c,v 1.4 2014/03/29 19:28:29 christos Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr_stubs.c,v 1.5 2016/10/19 00:08:42 nonaka Exp $");
#include <sys/param.h>
#include <sys/cpu.h>
@@ -67,12 +67,24 @@ const struct intrsw *powerpc_intrsw = &n
#define __stub __section(".stub") __noprofile
-void *intr_establish(int, int, int, int (*)(void *), void *) __stub;
+void *intr_establish(int, int, int, int (*)(void *), void *) __noprofile;
void *
intr_establish(int irq, int ipl, int ist, int (*func)(void *), void *arg)
{
- return (*powerpc_intrsw->intrsw_establish)(irq, ipl, ist, func, arg);
+ return (*powerpc_intrsw->intrsw_establish)(irq, ipl, ist, func, arg,
+ NULL);
+}
+
+void *intr_establish_xname(int, int, int, int (*)(void *), void *,
+ const char *) __stub;
+
+void *
+intr_establish_xname(int irq, int ipl, int ist, int (*func)(void *), void *arg,
+ const char *xname)
+{
+ return (*powerpc_intrsw->intrsw_establish)(irq, ipl, ist, func, arg,
+ xname);
}
void intr_disestablish(void *) __stub;
Index: src/sys/arch/prep/pci/pci_machdep.c
diff -u src/sys/arch/prep/pci/pci_machdep.c:1.41 src/sys/arch/prep/pci/pci_machdep.c:1.42
--- src/sys/arch/prep/pci/pci_machdep.c:1.41 Sat Oct 18 08:33:26 2014
+++ src/sys/arch/prep/pci/pci_machdep.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.41 2014/10/18 08:33:26 snj Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.42 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.41 2014/10/18 08:33:26 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.42 2016/10/19 00:08:42 nonaka Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -91,10 +91,17 @@ prep_pci_get_chipset_tag_indirect(pci_ch
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
pc->pc_msi_v = (void *)pc;
genppc_pci_chipset_msi_init(pc);
+ pc->pc_msix_v = (void *)pc;
+ genppc_pci_chipset_msix_init(pc);
+
pc->pc_conf_interrupt = genppc_pci_conf_interrupt;
pc->pc_decompose_tag = genppc_pci_indirect_decompose_tag;
pc->pc_conf_hook = prep_pci_conf_hook;
Index: src/sys/arch/prep/pci/prep_pciconf_direct.c
diff -u src/sys/arch/prep/pci/prep_pciconf_direct.c:1.9 src/sys/arch/prep/pci/prep_pciconf_direct.c:1.10
--- src/sys/arch/prep/pci/prep_pciconf_direct.c:1.9 Fri Oct 2 05:22:52 2015
+++ src/sys/arch/prep/pci/prep_pciconf_direct.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: prep_pciconf_direct.c,v 1.9 2015/10/02 05:22:52 msaitoh Exp $ */
+/* $NetBSD: prep_pciconf_direct.c,v 1.10 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright (c) 2002 Klaus J. Klein. All rights reserved.
@@ -39,7 +39,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: prep_pciconf_direct.c,v 1.9 2015/10/02 05:22:52 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: prep_pciconf_direct.c,v 1.10 2016/10/19 00:08:42 nonaka Exp $");
#include <sys/types.h>
#include <sys/param.h>
@@ -109,6 +109,17 @@ prep_pci_get_chipset_tag_direct(pci_chip
pc->pc_intr_evcnt = genppc_pci_intr_evcnt;
pc->pc_intr_establish = genppc_pci_intr_establish;
pc->pc_intr_disestablish = genppc_pci_intr_disestablish;
+ pc->pc_intr_setattr = genppc_pci_intr_setattr;
+ pc->pc_intr_type = genppc_pci_intr_type;
+ pc->pc_intr_alloc = genppc_pci_intr_alloc;
+ pc->pc_intr_release = genppc_pci_intr_release;
+ pc->pc_intx_alloc = genppc_pci_intx_alloc;
+
+ pc->pc_msi_v = NULL;
+ genppc_pci_chipset_msi_init(pc);
+
+ pc->pc_msix_v = NULL;
+ genppc_pci_chipset_msix_init(pc);
pc->pc_conf_interrupt = genppc_pci_conf_interrupt;
pc->pc_decompose_tag = prep_pci_direct_decompose_tag;
Index: src/sys/arch/sandpoint/include/pci_machdep.h
diff -u src/sys/arch/sandpoint/include/pci_machdep.h:1.9 src/sys/arch/sandpoint/include/pci_machdep.h:1.10
--- src/sys/arch/sandpoint/include/pci_machdep.h:1.9 Sat Mar 29 19:28:29 2014
+++ src/sys/arch/sandpoint/include/pci_machdep.h Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.h,v 1.9 2014/03/29 19:28:29 christos Exp $ */
+/* $NetBSD: pci_machdep.h,v 1.10 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -35,6 +35,7 @@
*/
#define __HAVE_PCIIDE_MACHDEP_COMPAT_INTR_ESTABLISH
+#define __HAVE_PCI_MSI_MSIX
/*
* be-specific PCI structure and type definitions.
@@ -56,6 +57,13 @@ typedef int pcitag_t;
typedef int pci_intr_handle_t;
extern struct powerpc_bus_dma_tag pci_bus_dma_tag;
+typedef enum {
+ PCI_INTR_TYPE_INTX = 0,
+ PCI_INTR_TYPE_MSI,
+ PCI_INTR_TYPE_MSIX,
+ PCI_INTR_TYPE_SIZE,
+} pci_intr_type_t;
+
/*
* Functions provided to machine-independent PCI code.
*/
@@ -75,4 +83,31 @@ const char *pci_intr_string(pci_chipset_
const struct evcnt *pci_intr_evcnt(pci_chipset_tag_t, pci_intr_handle_t);
void *pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
int, int (*)(void *), void *);
+void *pci_intr_establish_xname(pci_chipset_tag_t, pci_intr_handle_t,
+ int, int (*)(void *), void *, const char *);
void pci_intr_disestablish(pci_chipset_tag_t, void *);
+
+pci_intr_type_t pci_intr_type(pci_chipset_tag_t, pci_intr_handle_t);
+int pci_intr_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *, pci_intr_type_t);
+void pci_intr_release(pci_chipset_tag_t, pci_intr_handle_t *, int);
+int pci_intx_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **);
+
+/* experimental MSI support */
+int pci_msi_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *);
+int pci_msi_alloc_exact(const struct pci_attach_args *,
+ pci_intr_handle_t **, int);
+
+/* experimental MSI-X support */
+int pci_msix_alloc(const struct pci_attach_args *,
+ pci_intr_handle_t **, int *);
+int pci_msix_alloc_exact(const struct pci_attach_args *,
+ pci_intr_handle_t **, int);
+int pci_msix_alloc_map(const struct pci_attach_args *,
+ pci_intr_handle_t **, u_int *, int);
+
+void pci_conf_interrupt(pci_chipset_tag_t, int, int, int,
+ int, int *);
+int pci_conf_hook(pci_chipset_tag_t, int, int, int, pcireg_t);
Index: src/sys/arch/sandpoint/pci/pci_machdep.c
diff -u src/sys/arch/sandpoint/pci/pci_machdep.c:1.34 src/sys/arch/sandpoint/pci/pci_machdep.c:1.35
--- src/sys/arch/sandpoint/pci/pci_machdep.c:1.34 Fri Oct 2 05:22:52 2015
+++ src/sys/arch/sandpoint/pci/pci_machdep.c Wed Oct 19 00:08:42 2016
@@ -1,4 +1,4 @@
-/* $NetBSD: pci_machdep.c,v 1.34 2015/10/02 05:22:52 msaitoh Exp $ */
+/* $NetBSD: pci_machdep.c,v 1.35 2016/10/19 00:08:42 nonaka Exp $ */
/*
* Copyright (c) 1996 Christopher G. Demetriou. All rights reserved.
@@ -43,7 +43,7 @@
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.34 2015/10/02 05:22:52 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_machdep.c,v 1.35 2016/10/19 00:08:42 nonaka Exp $");
#include "opt_pci.h"
@@ -52,6 +52,7 @@ __KERNEL_RCSID(0, "$NetBSD: pci_machdep.
#include <sys/device.h>
#include <sys/errno.h>
#include <sys/extent.h>
+#include <sys/kmem.h>
#include <sys/malloc.h>
#include <sys/queue.h>
#include <sys/systm.h>
@@ -404,7 +405,7 @@ pci_intr_string(pci_chipset_tag_t pc, pc
}
const struct evcnt *
-pci_intr_evcnt(void *v, pci_intr_handle_t ih)
+pci_intr_evcnt(pci_chipset_tag_t pc, pci_intr_handle_t ih)
{
/* XXX for now, no evcnt parent reported */
@@ -425,9 +426,17 @@ pci_intr_setattr(pci_chipset_tag_t pc, p
}
void *
-pci_intr_establish(void *v, pci_intr_handle_t ih, int level,
+pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
int (*func)(void *), void *arg)
{
+
+ return pci_intr_establish_xname(pc, ih, level, func, arg, NULL);
+}
+
+void *
+pci_intr_establish_xname(pci_chipset_tag_t pc, pci_intr_handle_t ih, int level,
+ int (*func)(void *), void *arg, const char *xname)
+{
int type;
if (brdtype == BRD_STORCENTER && ih == 1) {
@@ -439,19 +448,20 @@ pci_intr_establish(void *v, pci_intr_han
* Using an edge-trigger fixes that and triggers the
* interrupt only once during probing.
*/
- type = IST_EDGE;
+ type = IST_EDGE;
} else
type = IST_LEVEL;
-
+
/*
* ih is the value assigned in pci_intr_map(), above.
* It's the EPIC IRQ #.
*/
- return intr_establish(ih + I8259_ICU, type, level, func, arg);
+ return intr_establish_xname(ih + I8259_ICU, type, level, func, arg,
+ xname);
}
void
-pci_intr_disestablish(void *v, void *cookie)
+pci_intr_disestablish(pci_chipset_tag_t pc, void *cookie)
{
intr_disestablish(cookie);
@@ -486,3 +496,63 @@ pci_conf_interrupt(pci_chipset_tag_t pc,
}
}
#endif
+
+int
+pci_intx_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihpp)
+{
+ pci_intr_handle_t *ihp;
+
+ ihp = kmem_alloc(sizeof(*ihp), KM_SLEEP);
+ if (ihp == NULL)
+ return ENOMEM;
+
+ if (pci_intr_map(pa, ihp)) {
+ kmem_free(ihp, sizeof(*ihp));
+ return EINVAL;
+ }
+
+ *ihpp = ihp;
+ return 0;
+}
+
+/* experimental MSI support */
+int
+pci_msi_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count)
+{
+
+ return EOPNOTSUPP;
+}
+
+int
+pci_msi_alloc_exact(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int count)
+{
+
+ return EOPNOTSUPP;
+}
+
+/* experimental MSI-X support */
+int
+pci_msix_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int *count)
+{
+
+ return EOPNOTSUPP;
+}
+
+int
+pci_msix_alloc_exact(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ int count)
+{
+
+ return EOPNOTSUPP;
+}
+
+int
+pci_msix_alloc_map(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+ u_int *table_indexes, int count)
+{
+
+ return EOPNOTSUPP;
+}