From owner-p4-projects@FreeBSD.ORG Sun Apr 9 21:00:05 2006 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 0992A16A406; Sun, 9 Apr 2006 21:00:05 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id D354E16A401 for ; Sun, 9 Apr 2006 21:00:04 +0000 (UTC) (envelope-from jmg@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [216.136.204.115]) by mx1.FreeBSD.org (Postfix) with ESMTP id 7344043D45 for ; Sun, 9 Apr 2006 21:00:04 +0000 (GMT) (envelope-from jmg@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.1/8.13.1) with ESMTP id k39L049d065499 for ; Sun, 9 Apr 2006 21:00:04 GMT (envelope-from jmg@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.1/8.13.1/Submit) id k39L03ai065493 for perforce@freebsd.org; Sun, 9 Apr 2006 21:00:03 GMT (envelope-from jmg@freebsd.org) Date: Sun, 9 Apr 2006 21:00:03 GMT Message-Id: <200604092100.k39L03ai065493@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to jmg@freebsd.org using -f From: John-Mark Gurney To: Perforce Change Reviews Cc: Subject: PERFORCE change 94869 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 09 Apr 2006 21:00:05 -0000 http://perforce.freebsd.org/chv.cgi?CH=94869 Change 94869 by jmg@jmg_carbon-60 on 2006/04/09 20:59:06 first attempt at reorginizing the nexus.. this makes devhandle an ivar, instead of having children pull it from RES_MEMORY, and this also sets up all the interrupts as resources from interrupt-map.. They are indexed by rid on the child, and return the parent's interrupt #... vnex will need to be updated, and I'll do this shortly... also teach hv_pci to pass through interrupt's to the layer, this could get pci ints working.. Affected files ... .. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/hv_pcivar.h#7 edit .. //depot/projects/kmacy_sun4v/src/sys/sun4v/include/nexusvar.h#3 edit .. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/hv_pci.c#30 edit .. //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/nexus.c#4 edit Differences ... ==== //depot/projects/kmacy_sun4v/src/sys/sun4v/include/hv_pcivar.h#7 (text+ko) ==== @@ -36,8 +36,7 @@ struct bus_dma_tag hs_dmatag; - struct resource *hs_intr; - void *hs_intrcookie; + struct resource *hs_intr[4]; struct rman hs_pci_intr_rman; ==== //depot/projects/kmacy_sun4v/src/sys/sun4v/include/nexusvar.h#3 (text+ko) ==== @@ -30,6 +30,15 @@ extern struct bus_dma_tag nexus_dmatag; -#endif /* _MACHINE_NEXUSVAR_H_ */ +enum nexus_ivars { + NEXUS_IVAR_DEVHANDLE, +}; + +#define NEXUS_ACCESSOR(var, ivar, type) \ + __BUS_ACCESSOR(nexus, var, NEXUS, ivar, type) +NEXUS_ACCESSOR(devhandle, DEVHANDLE, uint64_t) +#undef NEXUS_ACCESSOR + +#endif /* _MACHINE_NEXUSVAR_H_ */ ==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/hv_pci.c#30 (text+ko) ==== @@ -189,29 +189,12 @@ sc->hs_devhandle = SUN4V_REG_SPEC2CFG_HDL(reg); #endif - rid = 0; - if ((sc->hs_intr = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE)) == NULL) { - device_printf(dev, "couldn't map interrupt\n"); - return ENXIO; - } - - /* XXX - Should this be _CLK since we are redistributing intrs? */ - error = bus_setup_intr(dev, sc->hs_intr, INTR_MPSAFE|INTR_TYPE_MISC, - hvpci_intr, sc, &sc->hs_intrcookie); - if (error) { - bus_release_resource(dev, SYS_RES_IRQ, - rman_get_rid(sc->hs_intr), sc->hs_intr); - device_printf(dev, "bus_setup_intr: %d\n", error); - return error; - } - /* initalize intr resources */ sc->hs_pci_intr_rman.rm_type = RMAN_ARRAY; sc->hs_pci_intr_rman.rm_descr = "HyperVisor PCI Interrupts"; if (rman_init(&sc->hs_pci_intr_rman) != 0 || /* XXX - no clue where this should start or end */ - rman_manage_region(&sc->hs_pci_intr_rman, 0, 10) != 0) + rman_manage_region(&sc->hs_pci_intr_rman, 0, 3) != 0) panic("%s: failed to set up intr rman", __func__); /* Pull in the ra addresses out of OFW */ @@ -417,9 +400,37 @@ hvpci_setup_intr(device_t dev, device_t child, struct resource *ires, int flags, driver_intr_t *intr, void *arg, void **cookiep) { + struct hvpci_softc *sc; + device_t parent; + int pciintr; - device_printf(dev, "attempted setup_intr: child: %p, ires: %p, flags: %#x, intr: %p, arg: %p, cookiep: %p\n", - child, ires, flags, intr, arg, cookiep); + sc = device_get_softc(dev); + parent = device_get_parent(dev); + + /* we use 0 through 3 for INTx interrupts, while sun uses 1 through 4 */ + pciintr = rman_get_start(ires); + KASSERT(pciintr >= 0 && pciintr <= 3, + ("interrupt out of range")); + rid = pciintr + 1; + if (sc->hs_intr[pciintr] != NULL) + return (EBUSY); + + if ((sc->hs_intr[pciintr] = bus_alloc_resource_any(parent, SYS_RES_IRQ, + &rid, RF_SHAREABLE | RF_ACTIVE)) == NULL) { + device_printf(dev, "couldn't alloc interrupt\n"); + return (ENXIO); + } + + error = bus_setup_intr(parent, sc->hs_intr[pciintr], flags, intr, arg, + cookiep); + if (error) { + bus_release_resource(parent, SYS_RES_IRQ, + rman_get_rid(sc->hs_intr[pciintr]), sc->hs_intr[pciintr]); + sc->hs_intr[pciintr] = NULL; + device_printf(dev, "bus_setup_intr: %d\n", error); + return (error); + } + return (0); } @@ -427,6 +438,22 @@ hvpci_teardown_intr(device_t dev, device_t child, struct resource *vec, void *cookie) { + struct hvpci_softc *sc; + device_t parent; + int pciintr; + int error; + + sc = device_get_softc(dev); + parent = device_get_parent(dev); + pciintr = rman_get_start(vec); + + error = bus_teardown_intr(parent, sc->hs_intr[pciintr], cookie); + if (error) + return (error); + + bus_release_resource(parent, SYS_RES_IRQ, + rman_get_rid(sc->hs_intr[pciintr]), sc->hs_intr[pciintr]); + sc->hs_intr[pciintr] = NULL; return (0); } ==== //depot/projects/kmacy_sun4v/src/sys/sun4v/sun4v/nexus.c#4 (text+ko) ==== @@ -73,9 +73,7 @@ struct ofw_bus_devinfo ndi_obdinfo; struct resource_list ndi_rl; - /* Some common properties. */ - struct nexus_regs *ndi_reg; - int ndi_nreg; + devhandle_t ndi_devhandle; }; struct nexus_softc { @@ -88,6 +86,7 @@ static bus_print_child_t nexus_print_child; static bus_add_child_t nexus_add_child; static bus_probe_nomatch_t nexus_probe_nomatch; +static bus_read_ivar_t nexus_read_ivar; static bus_setup_intr_t nexus_setup_intr; static bus_teardown_intr_t nexus_teardown_intr; static bus_alloc_resource_t nexus_alloc_resource; @@ -114,7 +113,7 @@ /* Bus interface */ DEVMETHOD(bus_print_child, nexus_print_child), DEVMETHOD(bus_probe_nomatch, nexus_probe_nomatch), - DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_read_ivar, nexus_read_ivar), DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), DEVMETHOD(bus_add_child, nexus_add_child), DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), @@ -279,6 +278,25 @@ type != NULL ? type : "unknown"); } +static int +nexus_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) +{ + struct nexus_devinfo *ndi; + + ndi = device_get_ivars(child); + + switch (which) { + case NEXUS_IVAR_DEVHANDLE: + *(uint64_t *)result = ndi->ndi_devhandle; + break; + + default: + return (ENOENT); + } + + return (0); +} + #ifdef SUN4V @@ -286,29 +304,25 @@ nexus_setup_intr(device_t dev, device_t child, struct resource *res, int flags, driver_intr_t *intr, void *arg, void **cookiep) { + struct nexus_devinfo *ndi; + uint64_t ihdl; + uint64_t ino; + int error, cpuid; - uint64_t reg, nreg; - uint64_t ihdl, cfg; - uint64_t ino, nino; - int error, cpuid; + ndi = device_get_ivars(child); if (res == NULL) panic("%s: NULL interrupt resource!", __func__); printf("dev=%s child=%s\n", ofw_bus_get_name(dev), ofw_bus_get_name(child)); - if ((error = bus_get_resource(child, SYS_RES_MEMORY, 0, ®, &nreg))) - goto fail; - - if ((error = bus_get_resource(child, SYS_RES_IRQ, 0, &ino, &nino))) - goto fail; + ino = rman_get_start(ires); printf("child=%s reg=0x%lx ino=0x%lx\n", ofw_bus_get_name(child), - reg, ino); + ndi->ndi_devhandle, ino); - cfg = SUN4V_REG_SPEC2CFG_HDL(reg); - - if (hvio_intr_devino_to_sysino(cfg, (uint32_t)ino, &ihdl) != H_EOK) { + if (hvio_intr_devino_to_sysino(ndi->ndi_devhandle, (uint32_t)ino, + &ihdl) != H_EOK) { error = ENXIO; goto fail; } @@ -509,9 +523,9 @@ struct nexus_regs *reg; bus_addr_t phys; bus_size_t size; - uint32_t ign; + uint32_t ign, naddrcell, nintrcell; uint32_t *intr; - int i; + int i, rid; int nintr; int nreg; @@ -528,44 +542,39 @@ } resource_list_init(&ndi->ndi_rl); nreg = OF_getprop_alloc(node, "reg", sizeof(*reg), (void **)®); - if (nreg == -1) { - device_printf(dev, "<%s>: incomplete\n", - ndi->ndi_obdinfo.obd_name); + if (nreg != 1) { + device_printf(dev, "<%s>: incomplete: %d\n", + ndi->ndi_obdinfo.obd_name, nreg); nexus_destroy_dinfo(ndi); return (NULL); } - for (i = 0; i < nreg; i++) { - phys = NEXUS_REG_PHYS(®[i]); - size = NEXUS_REG_SIZE(®[i]); - resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i, phys, - phys + size - 1, size); - } + phys = NEXUS_REG_PHYS(®[0]); + ndi->ndi_devhandle = SUN4V_REG_SPEC2CFG_HDL(phys); free(reg, M_OFWPROP); - nintr = OF_getprop_alloc(node, "interrupts", sizeof(*intr), + if (OF_getprop(node, "#address-cells", &naddrcell, + sizeof *naddrcell) != sizeof *naddrcell || OF_getprop(node, + "#interrupt-cells", &nintrcell, sizeof *nintrcell) != + sizeof *nintrcell || nintrcell != 1) + panic("can't get cell sizes"); /* or invalid intr cell size */ + + nintr = OF_getprop_alloc(node, "interrupt-map", sizeof(*intr), (void **)&intr); - if (nintr > 0) { -#ifndef SUN4V - if (OF_getprop(node, cpu_impl < CPU_IMPL_ULTRASPARCIII ? - "upa-portid" : "portid", &ign, sizeof(ign)) <= 0) { - device_printf(dev, "<%s>: could not determine portid\n", - ndi->ndi_obdinfo.obd_name); - nexus_destroy_dinfo(ndi); - return (NULL); - } - - /* XXX Starfire */ - ign = (ign << INTMAP_IGN_SHIFT) & INTMAP_IGN_MASK; -#else - ign = 0; -#endif - for (i = 0; i < nintr; i++) { - intr[i] |= ign; - resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, i, intr[i], - intr[i], 1); - } - free(intr, M_OFWPROP); + for (i = 0; i < nintr; rid++, i += naddrcell + nintrcell + 2) { + /* + * interrupt-map is: + * addr,intr,phandle,parent's intr + */ + rid = intr[i + naddrcell]; + * XXX - technically, we need to pull the parent's + * #interrupt-cells, but we'll assume it's 1 like we enforce + * nintercell to be above. + */ + resource_list_add(&ndi->ndi_rl, SYS_RES_IRQ, rid, + intr[i + naddrcell + nintercell + 1], + intr[i + naddrcell + nintercell + 1], 1); } + free(intr, M_OFWPROP); return (ndi); }