Date: Sat, 1 Feb 2014 17:17:36 +0000 (UTC) From: Nathan Whitehorn <nwhitehorn@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r261351 - in head/sys: arm/arm arm/mv dev/fdt dev/ofw powerpc/ofw powerpc/powerpc powerpc/pseries Message-ID: <201402011717.s11HHaHD073266@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: nwhitehorn Date: Sat Feb 1 17:17:35 2014 New Revision: 261351 URL: http://svnweb.freebsd.org/changeset/base/261351 Log: Open Firmware interrupt specifiers can consist of arbitrary-length byte strings and include arbitrary information (IRQ line/domain/sense). When the ofw_bus_map_intr() API was introduced, it assumed that, as on most systems, these were either 1 cell, containing an interrupt line, or 2, containing a line number plus a sense code. It turns out a non-negligible number of ARM systems use 3 (or even 4!) cells for interrupts, so make this more general. Modified: head/sys/arm/arm/nexus.c head/sys/arm/mv/mv_pci.c head/sys/dev/fdt/fdt_common.c head/sys/dev/ofw/ofw_bus.h head/sys/dev/ofw/ofw_bus_if.m head/sys/dev/ofw/ofw_nexus.c head/sys/powerpc/ofw/ofw_pci.c head/sys/powerpc/ofw/ofw_pcib_pci.c head/sys/powerpc/ofw/ofw_pcibus.c head/sys/powerpc/powerpc/nexus.c head/sys/powerpc/pseries/vdevice.c Modified: head/sys/arm/arm/nexus.c ============================================================================== --- head/sys/arm/arm/nexus.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/arm/arm/nexus.c Sat Feb 1 17:17:35 2014 (r261351) @@ -98,7 +98,7 @@ static int nexus_teardown_intr(device_t, #ifdef FDT static int nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, - int irq); + int icells, pcell_t *intr); #endif static device_method_t nexus_methods[] = { @@ -339,15 +339,16 @@ nexus_deactivate_resource(device_t bus, #ifdef FDT static int -nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq) +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, + pcell_t *intr) { - pcell_t intr[2]; fdt_pic_decode_t intr_decode; phandle_t intr_offset; int i, rv, interrupt, trig, pol; intr_offset = OF_xref_phandle(iparent); - intr[0] = cpu_to_fdt32(irq); + for (i = 0; i < icells; i++) + intr[i] = cpu_to_fdt32(intr[i]); for (i = 0; fdt_pic_table[i] != NULL; i++) { intr_decode = fdt_pic_table[i]; @@ -355,13 +356,13 @@ nexus_ofw_map_intr(device_t dev, device_ if (rv == 0) { /* This was recognized as our PIC and decoded. */ - interrupt = FDT_MAP_IRQ(intr_parent, interrupt); + interrupt = FDT_MAP_IRQ(intr_parent, intr[0]); return (interrupt); } } /* Not in table, so guess */ - interrupt = FDT_MAP_IRQ(intr_parent, fdt32_to_cpu(*intr)); + interrupt = FDT_MAP_IRQ(intr_parent, intr[0]); return (interrupt); } Modified: head/sys/arm/mv/mv_pci.c ============================================================================== --- head/sys/arm/mv/mv_pci.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/arm/mv/mv_pci.c Sat Feb 1 17:17:35 2014 (r261351) @@ -1050,7 +1050,8 @@ mv_pcib_route_interrupt(device_t bus, de { struct mv_pcib_softc *sc; struct ofw_pci_register reg; - uint32_t pintr, mintr; + uint32_t pintr, mintr[4]; + int icells; phandle_t iparent; sc = device_get_softc(bus); @@ -1062,10 +1063,11 @@ mv_pcib_route_interrupt(device_t bus, de (pci_get_slot(dev) << OFW_PCI_PHYS_HI_DEVICESHIFT) | (pci_get_function(dev) << OFW_PCI_PHYS_HI_FUNCTIONSHIFT); - if (ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, ®, - sizeof(reg), &pintr, sizeof(pintr), &mintr, sizeof(mintr), - &iparent)) - return (ofw_bus_map_intr(dev, iparent, mintr)); + icells = ofw_bus_lookup_imap(ofw_bus_get_node(dev), &sc->sc_pci_iinfo, + ®, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr), + &iparent); + if (icells > 0) + return (ofw_bus_map_intr(dev, iparent, icells, mintr)); /* Maybe it's a real interrupt, not an intpin */ if (pin > 4) Modified: head/sys/dev/fdt/fdt_common.c ============================================================================== --- head/sys/dev/fdt/fdt_common.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/dev/fdt/fdt_common.c Sat Feb 1 17:17:35 2014 (r261351) @@ -501,11 +501,9 @@ fdt_intr_to_rl(device_t dev, phandle_t n icells = 1; } for (i = 0, k = 0; i < nintr; i += icells, k++) { - intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]); + intr[i] = ofw_bus_map_intr(dev, iparent, icells, intr); resource_list_add(rl, SYS_RES_IRQ, k, intr[i], intr[i], 1); - if (icells > 1) - ofw_bus_config_intr(dev, intr[i], intr[i+1]); } free(intr, M_OFWPROP); } Modified: head/sys/dev/ofw/ofw_bus.h ============================================================================== --- head/sys/dev/ofw/ofw_bus.h Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/dev/ofw/ofw_bus.h Sat Feb 1 17:17:35 2014 (r261351) @@ -71,15 +71,9 @@ ofw_bus_get_type(device_t dev) } static __inline int -ofw_bus_map_intr(device_t dev, phandle_t iparent, int irq) +ofw_bus_map_intr(device_t dev, phandle_t iparent, int icells, pcell_t *intr) { - return (OFW_BUS_MAP_INTR(dev, dev, iparent, irq)); -} - -static __inline int -ofw_bus_config_intr(device_t dev, int irq, int sense) -{ - return (OFW_BUS_CONFIG_INTR(dev, dev, irq, sense)); + return (OFW_BUS_MAP_INTR(dev, dev, iparent, icells, intr)); } #endif /* !_DEV_OFW_OFW_BUS_H_ */ Modified: head/sys/dev/ofw/ofw_bus_if.m ============================================================================== --- head/sys/dev/ofw/ofw_bus_if.m Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/dev/ofw/ofw_bus_if.m Sat Feb 1 17:17:35 2014 (r261351) @@ -57,7 +57,6 @@ CODE { static ofw_bus_get_node_t ofw_bus_default_get_node; static ofw_bus_get_type_t ofw_bus_default_get_type; static ofw_bus_map_intr_t ofw_bus_default_map_intr; - static ofw_bus_config_intr_t ofw_bus_default_config_intr; static const struct ofw_bus_devinfo * ofw_bus_default_get_devinfo(device_t bus, device_t dev) @@ -103,27 +102,15 @@ CODE { int ofw_bus_default_map_intr(device_t bus, device_t dev, phandle_t iparent, - int irq) + int icells, pcell_t *interrupt) { /* Propagate up the bus hierarchy until someone handles it. */ if (device_get_parent(bus) != NULL) return OFW_BUS_MAP_INTR(device_get_parent(bus), dev, - iparent, irq); + iparent, icells, interrupt); /* If that fails, then assume a one-domain system */ - return (irq); - } - - int - ofw_bus_default_config_intr(device_t bus, device_t dev, int irq, - int sense) - { - /* Propagate up the bus hierarchy until someone handles it. */ - if (device_get_parent(bus) != NULL) - return OFW_BUS_CONFIG_INTR(device_get_parent(bus), dev, - irq, sense); - - return (ENXIO); + return (interrupt[0]); } }; @@ -172,20 +159,14 @@ METHOD const char * get_type { } DEFAULT ofw_bus_default_get_type; # Map an (interrupt parent, IRQ) pair to a unique system-wide interrupt number. +# If the interrupt encoding includes a sense field, the interrupt sense will +# also be configured. METHOD int map_intr { device_t bus; device_t dev; phandle_t iparent; - int irq; + int icells; + pcell_t *interrupt; } DEFAULT ofw_bus_default_map_intr; -# Configure an interrupt using the device-tree encoded sense key (the second -# value in the interrupts property if interrupt-cells is 2). IRQ should be -# encoded as from ofw_bus_map_intr(). -METHOD int config_intr { - device_t bus; - device_t dev; - int irq; - int sense; -} DEFAULT ofw_bus_default_config_intr; Modified: head/sys/dev/ofw/ofw_nexus.c ============================================================================== --- head/sys/dev/ofw/ofw_nexus.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/dev/ofw/ofw_nexus.c Sat Feb 1 17:17:35 2014 (r261351) @@ -467,11 +467,10 @@ nexus_setup_dinfo(device_t dev, phandle_ OF_searchencprop(OF_xref_phandle(iparent), "#interrupt-cells", &icells, sizeof(icells)); for (i = 0; i < nintr; i+= icells) { - intr[i] = ofw_bus_map_intr(dev, iparent, intr[i]); + intr[i] = ofw_bus_map_intr(dev, iparent, icells, + &intr[i]); resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i], intr[i], 1); - if (icells > 1) - ofw_bus_config_intr(dev, intr[i], intr[i+1]); } free(intr, M_OFWPROP); } Modified: head/sys/powerpc/ofw/ofw_pci.c ============================================================================== --- head/sys/powerpc/ofw/ofw_pci.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/powerpc/ofw/ofw_pci.c Sat Feb 1 17:17:35 2014 (r261351) @@ -273,9 +273,7 @@ ofw_pci_route_interrupt(device_t bus, de &sc->sc_pci_iinfo, ®, sizeof(reg), &pintr, sizeof(pintr), mintr, sizeof(mintr), &iparent); if (intrcells) { - pintr = ofw_bus_map_intr(dev, iparent, mintr[0]); - if (intrcells == 2) - ofw_bus_config_intr(dev, pintr, mintr[1]); + pintr = ofw_bus_map_intr(dev, iparent, intrcells, mintr); return (pintr); } Modified: head/sys/powerpc/ofw/ofw_pcib_pci.c ============================================================================== --- head/sys/powerpc/ofw/ofw_pcib_pci.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/powerpc/ofw/ofw_pcib_pci.c Sat Feb 1 17:17:35 2014 (r261351) @@ -158,10 +158,8 @@ ofw_pcib_pci_route_interrupt(device_t br * it again on higher levels - that causes problems * in some cases, and never seems to be required. */ - mintr[0] = ofw_bus_map_intr(dev, iparent, mintr[0]); - if (intrcells == 2) - ofw_bus_config_intr(dev, mintr[0], mintr[1]); - + mintr[0] = ofw_bus_map_intr(dev, iparent, intrcells, + mintr); return (mintr[0]); } } else if (intpin >= 1 && intpin <= 4) { Modified: head/sys/powerpc/ofw/ofw_pcibus.c ============================================================================== --- head/sys/powerpc/ofw/ofw_pcibus.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/powerpc/ofw/ofw_pcibus.c Sat Feb 1 17:17:35 2014 (r261351) @@ -216,13 +216,9 @@ ofw_pcibus_enum_devtree(device_t dev, u_ "#interrupt-cells", &icells, sizeof(icells)); intr[0] = ofw_bus_map_intr(dev, iparent, - intr[0]); + icells, intr); } - if (iparent != 0 && icells > 1) - ofw_bus_config_intr(dev, intr[0], - intr[1]); - resource_list_add(&dinfo->opd_dinfo.resources, SYS_RES_IRQ, 0, intr[0], intr[0], 1); } @@ -309,18 +305,18 @@ ofw_pcibus_child_pnpinfo_str_method(devi static int ofw_pcibus_assign_interrupt(device_t dev, device_t child) { - ofw_pci_intr_t intr; + ofw_pci_intr_t intr[2]; phandle_t node, iparent; - int isz; + int isz, icells; node = ofw_bus_get_node(child); if (node == -1) { /* Non-firmware enumerated child, use standard routing */ - intr = pci_get_intpin(child); + intr[0] = pci_get_intpin(child); return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, - intr)); + intr[0])); } /* @@ -331,24 +327,28 @@ ofw_pcibus_assign_interrupt(device_t dev iparent = -1; if (OF_getprop(node, "interrupt-parent", &iparent, sizeof(iparent)) < 0) iparent = -1; + icells = 1; + if (iparent != -1) + OF_getprop(OF_xref_phandle(iparent), "#interrupt-cells", + &icells, sizeof(icells)); /* * Any AAPL,interrupts property gets priority and is * fully specified (i.e. does not need routing) */ - isz = OF_getprop(node, "AAPL,interrupts", &intr, sizeof(intr)); - if (isz == sizeof(intr)) - return ((iparent == -1) ? intr : ofw_bus_map_intr(dev, iparent, - intr)); + isz = OF_getprop(node, "AAPL,interrupts", intr, sizeof(intr)); + if (isz == sizeof(intr[0])*icells) + return ((iparent == -1) ? intr[0] : ofw_bus_map_intr(dev, + iparent, icells, intr)); - isz = OF_getprop(node, "interrupts", &intr, sizeof(intr)); - if (isz == sizeof(intr)) { + isz = OF_getprop(node, "interrupts", intr, sizeof(intr)); + if (isz == sizeof(intr[0])*icells) { if (iparent != -1) - intr = ofw_bus_map_intr(dev, iparent, intr); + intr[0] = ofw_bus_map_intr(dev, iparent, icells, intr); } else { /* No property: our best guess is the intpin. */ - intr = pci_get_intpin(child); + intr[0] = pci_get_intpin(child); } /* @@ -361,7 +361,7 @@ ofw_pcibus_assign_interrupt(device_t dev * will always use the route_interrupt method, and treat exceptions * on the level they become apparent. */ - return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr)); + return (PCIB_ROUTE_INTERRUPT(device_get_parent(dev), child, intr[0])); } static const struct ofw_bus_devinfo * Modified: head/sys/powerpc/powerpc/nexus.c ============================================================================== --- head/sys/powerpc/powerpc/nexus.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/powerpc/powerpc/nexus.c Sat Feb 1 17:17:35 2014 (r261351) @@ -75,7 +75,6 @@ static bus_bind_intr_t nexus_bind_intr; #endif static bus_config_intr_t nexus_config_intr; static ofw_bus_map_intr_t nexus_ofw_map_intr; -static ofw_bus_config_intr_t nexus_ofw_config_intr; static device_method_t nexus_methods[] = { /* Bus interface */ @@ -90,7 +89,6 @@ static device_method_t nexus_methods[] = /* ofw_bus interface */ DEVMETHOD(ofw_bus_map_intr, nexus_ofw_map_intr), - DEVMETHOD(ofw_bus_config_intr, nexus_ofw_config_intr), DEVMETHOD_END }; @@ -157,19 +155,16 @@ nexus_config_intr(device_t dev, int irq, } static int -nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int irq) +nexus_ofw_map_intr(device_t dev, device_t child, phandle_t iparent, int icells, + pcell_t *irq) { - return (MAP_IRQ(iparent, irq)); + u_int intr = MAP_IRQ(iparent, irq[0]); + if (icells > 1) + powerpc_fw_config_intr(irq[0], irq[1]); + return (intr); } static int -nexus_ofw_config_intr(device_t dev, device_t child, int irq, int sense) -{ - - return (powerpc_fw_config_intr(irq, sense)); -} - -static int nexus_activate_resource(device_t bus __unused, device_t child __unused, int type, int rid __unused, struct resource *r) { Modified: head/sys/powerpc/pseries/vdevice.c ============================================================================== --- head/sys/powerpc/pseries/vdevice.c Sat Feb 1 12:33:58 2014 (r261350) +++ head/sys/powerpc/pseries/vdevice.c Sat Feb 1 17:17:35 2014 (r261351) @@ -157,7 +157,7 @@ vdevice_attach(device_t dev) u_int irq = intr[i]; if (iparent != -1) irq = ofw_bus_map_intr(dev, iparent, - intr[i]); + icells, &intr[i]); resource_list_add(&dinfo->mdi_resources, SYS_RES_IRQ, i, irq, irq, i);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201402011717.s11HHaHD073266>