Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/arch/x86 add pci_intr_alloc() API



details:   https://anonhg.NetBSD.org/src/rev/effffd88ff23
branches:  trunk
changeset: 339415:effffd88ff23
user:      knakahara <knakahara%NetBSD.org@localhost>
date:      Tue Jul 21 03:10:42 2015 +0000

description:
add pci_intr_alloc() API

diffstat:

 sys/arch/x86/include/pci_machdep_common.h |   18 ++++-
 sys/arch/x86/pci/pci_intr_machdep.c       |  124 +++++++++++++++++++++++++++++-
 2 files changed, 139 insertions(+), 3 deletions(-)

diffs (191 lines):

diff -r 46097842faf4 -r effffd88ff23 sys/arch/x86/include/pci_machdep_common.h
--- a/sys/arch/x86/include/pci_machdep_common.h Tue Jul 21 02:04:24 2015 +0000
+++ b/sys/arch/x86/include/pci_machdep_common.h Tue Jul 21 03:10:42 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pci_machdep_common.h,v 1.18 2015/05/15 08:36:41 knakahara Exp $        */
+/*     $NetBSD: pci_machdep_common.h,v 1.19 2015/07/21 03:10:42 knakahara Exp $        */
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
@@ -120,6 +120,15 @@
 void           pci_intr_disestablish(pci_chipset_tag_t, void *);
 int            pci_intr_distribute(void *, const kcpuset_t *, kcpuset_t *);
 
+typedef enum {
+       PCI_INTR_TYPE_INTX = 0,
+       PCI_INTR_TYPE_MSI,
+       PCI_INTR_TYPE_MSIX,
+       PCI_INTR_TYPE_SIZE,
+} pci_intr_type_t;
+
+pci_intr_type_t        pci_intr_type(pci_intr_handle_t);
+
 /*
  * If device drivers use MSI/MSI-X, they should use these API for INTx
  * instead of pci_intr_map(), because of conforming the pci_intr_handle
@@ -128,6 +137,13 @@
 int            pci_intx_alloc(const struct pci_attach_args *,
                    pci_intr_handle_t **);
 
+/*
+ * Wrapper function for generally unitied allocation to fallback MSI-X/MSI/INTx
+ * automatically.
+ */
+int            pci_intr_alloc(const struct pci_attach_args *,
+                   pci_intr_handle_t **, int *, pci_intr_type_t);
+
 /* experimental MSI support */
 int            pci_msi_count(const struct pci_attach_args *);
 int            pci_msi_alloc(const struct pci_attach_args *,
diff -r 46097842faf4 -r effffd88ff23 sys/arch/x86/pci/pci_intr_machdep.c
--- a/sys/arch/x86/pci/pci_intr_machdep.c       Tue Jul 21 02:04:24 2015 +0000
+++ b/sys/arch/x86/pci/pci_intr_machdep.c       Tue Jul 21 03:10:42 2015 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: pci_intr_machdep.c,v 1.33 2015/05/15 08:36:41 knakahara Exp $  */
+/*     $NetBSD: pci_intr_machdep.c,v 1.34 2015/07/21 03:10:42 knakahara Exp $  */
 
 /*-
  * Copyright (c) 1997, 1998, 2009 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.33 2015/05/15 08:36:41 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.34 2015/07/21 03:10:42 knakahara Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -350,6 +350,20 @@
 }
 
 #if NIOAPIC > 0
+pci_intr_type_t
+pci_intr_type(pci_intr_handle_t ih)
+{
+
+       if (INT_VIA_MSI(ih)) {
+               if (MSI_INT_IS_MSIX(ih))
+                       return PCI_INTR_TYPE_MSIX;
+               else
+                       return PCI_INTR_TYPE_MSI;
+       } else {
+               return PCI_INTR_TYPE_INTX;
+       }
+}
+
 static void
 x86_pci_intx_release(pci_chipset_tag_t pc, pci_intr_handle_t *pih)
 {
@@ -404,6 +418,112 @@
        return error;
 }
 
+/*
+ * Interrupt handler allocation utility. This function calls each allocation
+ * function as specified by arguments.
+ * Currently callee functions are pci_intx_alloc(), pci_msi_alloc_exact(),
+ * and pci_msix_alloc_exact().
+ * pa       : pci_attach_args
+ * ihps     : interrupt handlers
+ * counts   : The array of number of required interrupt handlers.
+ *            It is overwritten by allocated the number of handlers.
+ *            CAUTION: The size of counts[] must be PCI_INTR_TYPE_SIZE.
+ * max_type : "max" type of using interrupts. See below.
+ *     e.g.
+ *         If you want to use 5 MSI-X, 1 MSI, or INTx, you use "counts" as
+ *             int counts[PCI_INTR_TYPE_SIZE];
+ *             counts[PCI_INTR_TYPE_MSIX] = 5;
+ *             counts[PCI_INTR_TYPE_MSI] = 1;
+ *             counts[PCI_INTR_TYPE_INTX] = 1;
+ *             error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSIX);
+ *
+ *         If you want to use hardware max number MSI-X or 1 MSI,
+ *         and not to use INTx, you use "counts" as
+ *             int counts[PCI_INTR_TYPE_SIZE];
+ *             counts[PCI_INTR_TYPE_MSIX] = -1;
+ *             counts[PCI_INTR_TYPE_MSI] = 1;
+ *             counts[PCI_INTR_TYPE_INTX] = 0;
+ *             error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSIX);
+ *
+ *         If you want to use 3 MSI or INTx, you can use "counts" as
+ *             int counts[PCI_INTR_TYPE_SIZE];
+ *             counts[PCI_INTR_TYPE_MSI] = 3;
+ *             counts[PCI_INTR_TYPE_INTX] = 1;
+ *             error = pci_intr_alloc(pa, ihps, counts, PCI_INTR_TYPE_MSI);
+ *
+ *         If you want to use 1 MSI or INTx (probably most general usage),
+ *         you can simply use this API like
+ *         below
+ *             error = pci_intr_alloc(pa, ihps, NULL, 0);
+ *                                                    ^ ignored
+ */
+int
+pci_intr_alloc(const struct pci_attach_args *pa, pci_intr_handle_t **ihps,
+    int *counts, pci_intr_type_t max_type)
+{
+       int error;
+       int intx_count, msi_count, msix_count;
+
+       intx_count = msi_count = msix_count = 0;
+       if (counts == NULL) { /* simple pattern */
+               msi_count = 1;
+               intx_count = 1;
+       } else {
+               switch(max_type) {
+               case PCI_INTR_TYPE_MSIX:
+                       msix_count = counts[PCI_INTR_TYPE_MSIX];
+                       /* FALLTHROUGH */
+               case PCI_INTR_TYPE_MSI:
+                       msi_count = counts[PCI_INTR_TYPE_MSI];
+                       /* FALLTHROUGH */
+               case PCI_INTR_TYPE_INTX:
+                       intx_count = counts[PCI_INTR_TYPE_INTX];
+                       break;
+               default:
+                       return EINVAL;
+               }
+       }
+
+       memset(counts, 0, sizeof(counts[0]) * PCI_INTR_TYPE_SIZE);
+       error = EINVAL;
+
+       /* try MSI-X */
+       if (msix_count == -1) /* use hardware max */
+               msix_count = pci_msix_count(pa);
+       if (msix_count > 0) {
+               error = pci_msix_alloc_exact(pa, ihps, msix_count);
+               if (error == 0) {
+                       counts[PCI_INTR_TYPE_MSIX] = msix_count;
+                       goto out;
+               }
+       }
+
+       /* try MSI */
+       if (msi_count == -1) /* use hardware max */
+               msi_count = pci_msi_count(pa);
+       if (msi_count > 0) {
+               error = pci_msi_alloc_exact(pa, ihps, msi_count);
+               if (error == 0) {
+                       if (counts != NULL) {
+                               counts[PCI_INTR_TYPE_MSI] = msi_count;
+                               goto out;
+                       }
+               }
+       }
+
+       /* try INTx */
+       if (intx_count != 0) { /* The number of INTx is always 1. */
+               error = pci_intx_alloc(pa, ihps);
+               if (error == 0) {
+                       if (counts != NULL)
+                               counts[PCI_INTR_TYPE_INTX] = 1;
+               }
+       }
+
+ out:
+       return error;
+}
+
 void
 pci_intr_release(pci_chipset_tag_t pc, pci_intr_handle_t *pih, int count)
 {



Home | Main Index | Thread Index | Old Index