PERFORCE change 94869 for review

John-Mark Gurney jmg at FreeBSD.org
Sun Apr 9 21:00:05 UTC 2006


http://perforce.freebsd.org/chv.cgi?CH=94869

Change 94869 by jmg at 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, &reg, &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 **)&reg);
-	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(&reg[i]);
-		size = NEXUS_REG_SIZE(&reg[i]);
-		resource_list_add(&ndi->ndi_rl, SYS_RES_MEMORY, i, phys,
-		    phys + size - 1, size);
-	}
+	phys = NEXUS_REG_PHYS(&reg[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);
 }


More information about the p4-projects mailing list