Source-Changes-HG archive

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

[src/trunk]: src/sys/dev/fdt FDT Interrupt handling - change memory allocation



details:   https://anonhg.NetBSD.org/src/rev/379e31505b9c
branches:  trunk
changeset: 342847:379e31505b9c
user:      marty <marty%NetBSD.org@localhost>
date:      Sun Jan 10 23:01:29 2016 +0000

description:
FDT Interrupt handling - change memory allocation

This version does dynamic allocation of the specifier array.

diffstat:

 sys/dev/fdt/fdt_intr.c |  62 +++++++++++++++++++++++++++++++++----------------
 1 files changed, 42 insertions(+), 20 deletions(-)

diffs (167 lines):

diff -r f3def86fa00f -r 379e31505b9c sys/dev/fdt/fdt_intr.c
--- a/sys/dev/fdt/fdt_intr.c    Sun Jan 10 22:22:16 2016 +0000
+++ b/sys/dev/fdt/fdt_intr.c    Sun Jan 10 23:01:29 2016 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: fdt_intr.c,v 1.6 2016/01/07 04:26:44 marty Exp $ */
+/* $NetBSD: fdt_intr.c,v 1.7 2016/01/10 23:01:29 marty Exp $ */
 
 /*-
  * Copyright (c) 2015 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fdt_intr.c,v 1.6 2016/01/07 04:26:44 marty Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fdt_intr.c,v 1.7 2016/01/10 23:01:29 marty Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -36,7 +36,6 @@
 #include <libfdt.h>
 #include <dev/fdt/fdtvar.h>
 
-#define MAX_SPEC_LENGTH 6
 struct fdtbus_interrupt_controller {
        device_t ic_dev;
        int ic_phandle;
@@ -123,33 +122,41 @@
 fdtbus_intr_establish(int phandle, u_int index, int ipl, int flags,
     int (*func)(void *), void *arg)
 {
+       void * result = NULL;
        u_int *specifier;
-       u_int maxspec[MAX_SPEC_LENGTH];
+       u_int spec_length;
        int ihandle;
        struct fdtbus_interrupt_controller *ic;
 
        if (has_interrupt_map(phandle)) {
-               specifier = get_entry_from_map(phandle, index, maxspec);
+               specifier = get_entry_from_map(phandle, index, &spec_length);
                ihandle = be32toh(specifier[1]);
                ihandle = fdtbus_get_phandle_from_native(ihandle);
                specifier += 2;
        } else {
-               specifier = get_specifier_by_index(phandle, index, maxspec);
+               specifier = get_specifier_by_index(phandle, index,
+                                                  &spec_length);
                ihandle = phandle;
        }
        if (specifier == NULL) {
                printf("%s: Unable to get specifier %d for phandle %d\n",
                       __func__, index, phandle);
-               return NULL;
+               goto done;
        }
        ic = fdtbus_get_interrupt_controller(ihandle);
        if (ic == NULL) {
                printf("%s: Unable to get interrupt controller for %d\n",
                       __func__, ihandle);
-               return NULL;
+               goto done;
        }
-       return ic->ic_funcs->establish(ic->ic_dev, specifier,
+       result = ic->ic_funcs->establish(ic->ic_dev, specifier,
                                               ipl, flags, func, arg);
+done:
+       if (has_interrupt_map(phandle))
+           specifier -= 2;
+       if (specifier && spec_length > 0)
+               kmem_free(specifier, spec_length);
+       return result;
 }
 
 void
@@ -166,31 +173,40 @@
 bool
 fdtbus_intr_str(int phandle, u_int index, char *buf, size_t buflen)
 {
+       bool result = false;
        struct fdtbus_interrupt_controller *ic;
        int ihandle;
        u_int *specifier;
-       u_int maxspec[MAX_SPEC_LENGTH];
+       u_int spec_length;
        if (has_interrupt_map(phandle)) {
-               specifier = get_entry_from_map(phandle, index, maxspec);
+               specifier = get_entry_from_map(phandle, index,
+                       &spec_length);
                ihandle = be32toh(specifier[1]);
                ihandle = fdtbus_get_phandle_from_native(ihandle);
                specifier += 2;
        } else {
                ihandle = phandle;
-               specifier = get_specifier_by_index(phandle, index, maxspec);
+               specifier = get_specifier_by_index(phandle, index,
+                                                  &spec_length);
        }
        if (specifier == NULL) {
                printf("%s: Unable to get specifier %d for phandle %d\n",
                       __func__, index, phandle);
-               return false;
+               goto done;
        }
        ic = fdtbus_get_interrupt_controller(ihandle);
        if (ic == NULL) {
                printf("%s: Unable to get interrupt controller for %d\n",
                       __func__, ihandle);
-               return false;
+               goto done;
        }
-       return ic->ic_funcs->intrstr(ic->ic_dev, specifier, buf, buflen);
+       result = ic->ic_funcs->intrstr(ic->ic_dev, specifier, buf, buflen);
+done:
+       if (has_interrupt_map(phandle))
+           specifier -= 2;
+       if (specifier && spec_length > 0)
+               kmem_free(specifier, spec_length);
+       return result;
 }
 
 /*
@@ -232,7 +248,7 @@
  *
  */
 static u_int *
-get_entry_from_map(int phandle, int pindex, u_int *specifier)
+get_entry_from_map(int phandle, int pindex, u_int *spec_length)
 {
        int intr_cells;
        int intr_parent;
@@ -262,9 +278,11 @@
                u_int pintr_cells;
                of_getprop_uint32(parent, "#interrupt-cells", &pintr_cells);
                if (index == pindex) {
-                       for (int i = 0; i < pintr_cells; i++)
-                               specifier[i] =  p[i];
-                       result = specifier;
+                       result = kmem_alloc((pintr_cells + 2) * sizeof(u_int),
+                                           KM_SLEEP);
+                       *spec_length = (pintr_cells + 2) * sizeof (u_int);
+                       for (int i = 0; i < pintr_cells + 2; i++)
+                               result[i] =  p[i];
                        goto done;
                                                                        
                }
@@ -287,9 +305,11 @@
  * and return a pointer to it.
  *
  */
-static u_int *get_specifier_by_index(int phandle, int pindex, u_int *specifier)
+static u_int *get_specifier_by_index(int phandle, int pindex,
+                                    u_int *spec_length)
 {
        u_int *specifiers;
+       u_int *specifier;
        int interrupt_parent, interrupt_cells, len;
 
        interrupt_parent = fdtbus_get_interrupt_parent(phandle);
@@ -326,6 +346,8 @@
                kmem_free(specifiers, len);
                return NULL;
        }
+       specifier = kmem_alloc(interrupt_cells * sizeof(u_int), KM_SLEEP);
+       *spec_length = interrupt_cells * sizeof(u_int);
        for (int i = 0; i < interrupt_cells; i++)
                specifier[i] = specifiers[pindex * clen + i];
        kmem_free(specifiers, len);



Home | Main Index | Thread Index | Old Index