Date: Tue, 29 Mar 2011 00:36:36 +0000 (UTC) From: Marcel Moolenaar <marcel@FreeBSD.org> To: src-committers@freebsd.org, svn-src-projects@freebsd.org Subject: svn commit: r220119 - in projects/altix/sys/ia64: include sgisn Message-ID: <201103290036.p2T0aaGq011444@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: marcel Date: Tue Mar 29 00:36:36 2011 New Revision: 220119 URL: http://svn.freebsd.org/changeset/base/220119 Log: o Fleshed-out shub driver that creates pcib children. o Modified pcib driver that attaches to shub. o Slightly tweaked PROM-defined structures. Modified: projects/altix/sys/ia64/include/sgisn.h projects/altix/sys/ia64/sgisn/sgisn_pcib.c projects/altix/sys/ia64/sgisn/sgisn_shub.c Modified: projects/altix/sys/ia64/include/sgisn.h ============================================================================== --- projects/altix/sys/ia64/include/sgisn.h Tue Mar 29 00:33:02 2011 (r220118) +++ projects/altix/sys/ia64/include/sgisn.h Tue Mar 29 00:36:36 2011 (r220119) @@ -29,6 +29,7 @@ #define _MACHINE_SGISN_H_ /* SAL functions */ +#define SAL_SGISN_KLCONFIG_ADDR 0x02000005 #define SAL_SGISN_SAPIC_INFO 0x0200001d #define SAL_SGISN_SN_INFO 0x0200001e #define SAL_SGISN_PUTC 0x02000021 @@ -38,6 +39,8 @@ #define SAL_SGISN_IOHUB_INFO 0x02000055 #define SAL_SGISN_IOBUS_INFO 0x02000056 #define SAL_SGISN_IODEV_INFO 0x02000057 +#define SAL_SGISN_FEATURE_GET_PROM 0x02000065 +#define SAL_SGISN_FEATURE_SET_OS 0x02000066 #define SGISN_GEOID_MODULE(id) (((id) >> 0) & 0xffffffffu) #define SGISN_GEOID_TYPE(id) (((id) >> 32) & 0xff) @@ -61,23 +64,39 @@ #define SGISN_HUB_NITTES 8 #define SGISN_HUB_NWIDGETS 16 +#define SHUB_IVAR_PCIBUS 1 +#define SHUB_IVAR_PCISEG 2 + +struct sgisn_fwhub; + struct sgisn_widget { uint32_t wgt_hwmfg; uint32_t wgt_hwrev; uint32_t wgt_hwpn; uint8_t wgt_port; - char _pad[3]; - uint64_t wgt_private; - uint64_t wgt_provider; + uint8_t _pad[3]; + struct sgisn_fwhub *wgt_hub; + uint64_t wgt_funcs; uint64_t wgt_vertex; }; -struct sgisn_hub { +struct sgisn_fwbus { + uint32_t bus_asic; + uint32_t bus_xid; + uint32_t bus_busnr; + uint32_t bus_segment; + uint64_t bus_ioport_addr; + uint64_t bus_memio_addr; + uint64_t bus_base; + struct sgisn_widget *bus_wgt_info; +}; + +struct sgisn_fwhub { uint64_t hub_geoid; uint16_t hub_nasid; uint16_t hub_peer_nasid; - char _pad[4]; - uint64_t hub_pointer; + uint32_t _pad; + void *hub_widgets; uint64_t hub_dma_itte[SGISN_HUB_NITTES]; struct sgisn_widget hub_widget[SGISN_HUB_NWIDGETS]; @@ -88,29 +107,33 @@ struct sgisn_hub { uint32_t hub_pci_maxbus; }; -struct sgisn_irq { - uint64_t irq_unused; - uint16_t irq_nasid; - char _pad1[2]; - u_int irq_slice; - u_int irq_cpuid; - u_int irq_no; - u_int irq_pin; - uint64_t irq_xtaddr; - u_int irq_br_type; - char _pad2[4]; - uint64_t irq_bridge; - uint64_t irq_io_info; - u_int irq_last; - u_int irq_cookie; - u_int irq_flags; - u_int irq_refcnt; +struct sgisn_fwirq { + uint64_t _obsolete; + uint16_t irq_tgt_nasid; + uint16_t _pad1; + uint32_t irq_tgt_slice; + uint32_t irq_cpuid; + uint32_t irq_nr; + uint32_t irq_pin; + uint64_t irq_tgt_xtaddr; + uint32_t irq_br_type; + uint32_t _pad2; + void *irq_bridge; /* Originating */ + void *irq_io_info; + uint32_t irq_last; + uint32_t irq_cookie; + uint32_t irq_flags; + uint32_t irq_refcnt; }; -struct sgisn_dev { +struct sgisn_fwdev { uint64_t dev_bar[6]; - uint64_t dev_rom; + uint64_t dev_romaddr; uint64_t dev_handle; + struct sgisn_fwbus *dev_bus_softc; + struct sgisn_fwdev *dev_parent; + void *dev_os_devptr; + struct sgisn_fwirq *dev_irq; }; #endif /* !_MACHINE_SGISN_H_ */ Modified: projects/altix/sys/ia64/sgisn/sgisn_pcib.c ============================================================================== --- projects/altix/sys/ia64/sgisn/sgisn_pcib.c Tue Mar 29 00:33:02 2011 (r220118) +++ projects/altix/sys/ia64/sgisn/sgisn_pcib.c Tue Mar 29 00:36:36 2011 (r220119) @@ -50,9 +50,8 @@ __FBSDID("$FreeBSD$"); #include <machine/sal.h> #include <machine/sgisn.h> -static struct sgisn_hub sgisn_hub; -static struct sgisn_dev sgisn_dev; -static struct sgisn_irq sgisn_irq; +static struct sgisn_fwdev sgisn_dev; +static struct sgisn_fwirq sgisn_irq; struct sgisn_pcib_softc { device_t sc_dev; @@ -62,7 +61,6 @@ struct sgisn_pcib_softc { }; static int sgisn_pcib_attach(device_t); -static void sgisn_pcib_identify(driver_t *, device_t); static int sgisn_pcib_probe(device_t); static int sgisn_pcib_activate_resource(device_t, device_t, int, int, @@ -84,7 +82,6 @@ static int sgisn_pcib_scan(struct sgisn_ */ static device_method_t sgisn_pcib_methods[] = { /* Device interface */ - DEVMETHOD(device_identify, sgisn_pcib_identify), DEVMETHOD(device_probe, sgisn_pcib_probe), DEVMETHOD(device_attach, sgisn_pcib_attach), @@ -116,7 +113,7 @@ static driver_t sgisn_pcib_driver = { devclass_t pcib_devclass; -DRIVER_MODULE(pcib, nexus, sgisn_pcib_driver, pcib_devclass, 0, 0); +DRIVER_MODULE(pcib, shub, sgisn_pcib_driver, pcib_devclass, 0, 0); static int sgisn_pcib_maxslots(device_t dev) @@ -184,9 +181,30 @@ sgisn_pcib_activate_resource(device_t de if (type == SYS_RES_IRQ) { /* For now, only warn when there's a mismatch. */ - if (paddr != sgisn_irq.irq_no) + if (paddr != sgisn_irq.irq_nr) device_printf(dev, "interrupt mismatch: (actual=%u)\n", - sgisn_irq.irq_no); + sgisn_irq.irq_nr); + + printf("XXX: %s: %u, %u, %u, %u, %u, %#lx\n", __func__, + sgisn_irq.irq_tgt_nasid, sgisn_irq.irq_tgt_slice, + sgisn_irq.irq_cpuid, sgisn_irq.irq_nr, sgisn_irq.irq_pin, + sgisn_irq.irq_tgt_xtaddr); + printf("\t%u, %p, %p, %u, %#x, %#x, %u\n", sgisn_irq.irq_br_type, + sgisn_irq.irq_bridge, sgisn_irq.irq_io_info, sgisn_irq.irq_last, + sgisn_irq.irq_cookie, sgisn_irq.irq_flags, sgisn_irq.irq_refcnt); + +#if 0 + r = ia64_sal_entry(SAL_SGISN_INTERRUPT, 1 /*alloc*/, + sgisn_irq.irq_tgt_nasid, + (sgisn_irq.irq_bridge >> 24) & 15 + ia64_tpa((uintptr_t)&sgisn_irq), + paddr, + sgisn_irq.irq_tgt_nasid, + sgisn_irq.irq_tgt_slice); + if (r.status != 0) + return (ENXIO); +#endif + goto out; } @@ -209,44 +227,19 @@ sgisn_pcib_activate_resource(device_t de return (rman_activate_resource(res)); } -static void -sgisn_pcib_identify(driver_t *drv, device_t bus) -{ - struct ia64_sal_result r; - device_t dev; - struct sgisn_pcib_softc *sc; - void *addr; - u_int busno, segno; - - sgisn_hub.hub_pci_maxseg = 0xffffffff; - sgisn_hub.hub_pci_maxbus = 0xff; - r = ia64_sal_entry(SAL_SGISN_IOHUB_INFO, PCPU_GET(md.sgisn_nasid), - ia64_tpa((uintptr_t)&sgisn_hub), 0, 0, 0, 0, 0); - if (r.sal_status != 0) - return; - - for (segno = 0; segno <= sgisn_hub.hub_pci_maxseg; segno++) { - for (busno = 0; busno <= sgisn_hub.hub_pci_maxbus; busno++) { - r = ia64_sal_entry(SAL_SGISN_IOBUS_INFO, segno, busno, - ia64_tpa((uintptr_t)&addr), 0, 0, 0, 0); - - if (r.sal_status == 0 && addr != NULL) { - dev = BUS_ADD_CHILD(bus, 0, drv->name, -1); - if (dev == NULL) - continue; - device_set_driver(dev, drv); - sc = device_get_softc(dev); - sc->sc_promaddr = addr; - sc->sc_domain = segno; - sc->sc_busnr = busno; - } - } - } -} - static int sgisn_pcib_probe(device_t dev) { + device_t parent; + uintptr_t bus, seg; + + parent = device_get_parent(dev); + if (parent == NULL) + return (ENXIO); + + if (BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCISEG, &seg) || + BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCIBUS, &bus)) + return (ENXIO); device_set_desc(dev, "SGI PCI-X host controller"); return (BUS_PROBE_DEFAULT); @@ -256,10 +249,18 @@ static int sgisn_pcib_attach(device_t dev) { struct sgisn_pcib_softc *sc; + device_t parent; + uintptr_t bus, seg; sc = device_get_softc(dev); sc->sc_dev = dev; + parent = device_get_parent(dev); + BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCIBUS, &bus); + sc->sc_busnr = bus; + BUS_READ_IVAR(parent, dev, SHUB_IVAR_PCISEG, &seg); + sc->sc_domain = seg; + #if 0 sgisn_pcib_scan(sc, sc->sc_busnr, sgisn_pcib_maxslots(dev)); #endif @@ -301,8 +302,8 @@ sgisn_pcib_write_ivar(device_t dev, devi static int sgisn_pcib_scan(struct sgisn_pcib_softc *sc, u_int bus, u_int maxslot) { - static struct sgisn_dev dev; - static struct sgisn_irq irq; + static struct sgisn_fwdev dev; + static struct sgisn_fwirq irq; struct ia64_sal_result r; u_int devfn, func, maxfunc, slot; uint8_t hdrtype; Modified: projects/altix/sys/ia64/sgisn/sgisn_shub.c ============================================================================== --- projects/altix/sys/ia64/sgisn/sgisn_shub.c Tue Mar 29 00:33:02 2011 (r220118) +++ projects/altix/sys/ia64/sgisn/sgisn_shub.c Tue Mar 29 00:36:36 2011 (r220119) @@ -32,6 +32,7 @@ __FBSDID("$FreeBSD$"); #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <sys/malloc.h> #include <sys/pcpu.h> #include <sys/rman.h> @@ -48,14 +49,16 @@ __FBSDID("$FreeBSD$"); #include <contrib/dev/acpica/include/actables.h> #include <dev/acpica/acpivar.h> -// XXX static struct sgisn_hub sgisn_hub; - struct sgisn_shub_softc { - struct sgisn_hub sc_prom_hub; + struct sgisn_fwhub *sc_fwhub; device_t sc_dev; - void *sc_promaddr; + vm_paddr_t sc_membase; + vm_size_t sc_memsize; u_int sc_domain; - u_int sc_busnr; + u_int sc_hubtype; /* SHub type (0=SHub1, 1=SHub2) */ + u_int sc_nasid_mask; + u_int sc_nasid_shft; + u_int sc_nasid; }; static int sgisn_shub_attach(device_t); @@ -204,7 +207,7 @@ sgisn_shub_dump_sn_info(struct ia64_sal_ } static void -sgisn_shub_srat_parse(ACPI_SUBTABLE_HEADER *entry, void *arg) +sgisn_shub_identify_srat_cb(ACPI_SUBTABLE_HEADER *entry, void *arg) { ACPI_SRAT_CPU_AFFINITY *cpu; ACPI_SRAT_MEM_AFFINITY *mem; @@ -215,7 +218,7 @@ sgisn_shub_srat_parse(ACPI_SUBTABLE_HEAD /* * Use all possible entry types for learning about domains. - * This probably is highly redundant and could possible be + * This probably is highly redundant and could possibly be * wrong, but it seems more harmful to miss a domain than * anything else. */ @@ -244,7 +247,7 @@ sgisn_shub_srat_parse(ACPI_SUBTABLE_HEAD return; if (bootverbose) - printf("%s: found now domain %u\n", sgisn_shub_name, domain); + printf("%s: new domain %u\n", sgisn_shub_name, domain); /* * First encounter of this domain. Add a SHub device with a unit @@ -285,37 +288,175 @@ sgisn_shub_identify(driver_t *drv, devic } acpi_walk_subtables((uint8_t *)ptr + sizeof(ACPI_TABLE_SRAT), - (uint8_t *)ptr + tbl->Length, sgisn_shub_srat_parse, bus); + (uint8_t *)ptr + tbl->Length, sgisn_shub_identify_srat_cb, bus); } static int sgisn_shub_probe(device_t dev) { + struct ia64_sal_result r; + char desc[80]; + u_int v; + + /* + * NOTICE: This can only be done on a CPU that's connected to the + * FSB of the SHub ASIC. As such, the BSP can only validly probe + * the SHub it's connected to. + * + * In order to probe and attach SHubs in other domains, we need to + * defer to some CPU connected to that SHub. + * + * XXX For now, we assume that SHub types are the same across the + * system, so we simply query the SHub in our domain and pretend + * we queried the one corresponding to the domain this instance + * refers to. + */ + r = ia64_sal_entry(SAL_SGISN_SN_INFO, 0, 0, 0, 0, 0, 0, 0); + if (r.sal_status != 0) + return (ENXIO); + + v = (r.sal_result[0] & 0xff) + 1;; + snprintf(desc, sizeof(desc), "SGI SHub%u ASIC", v); + device_set_desc_copy(dev, desc); + return (BUS_PROBE_DEFAULT); +} + +static void +sgisn_shub_attach_srat_cb(ACPI_SUBTABLE_HEADER *entry, void *arg) +{ + device_t dev = arg; + ACPI_SRAT_MEM_AFFINITY *mem; struct sgisn_shub_softc *sc; + + if (entry->Type != ACPI_SRAT_TYPE_MEMORY_AFFINITY) + return; sc = device_get_softc(dev); - device_set_desc(dev, "SGI SHub ASIC "); - return (BUS_PROBE_DEFAULT); + mem = (ACPI_SRAT_MEM_AFFINITY *)(void *)entry; + if (mem->ProximityDomain != sc->sc_domain) + return; + if ((mem->Flags & ACPI_SRAT_MEM_ENABLED) == 0) + return; + + sc->sc_membase = mem->BaseAddress; + sc->sc_memsize = mem->Length; } static int sgisn_shub_attach(device_t dev) { + struct ia64_sal_result r; struct sgisn_shub_softc *sc; + ACPI_TABLE_HEADER *tbl; + device_t child; + void *ptr; + u_long addr; + u_int bus, seg, wdgt; sc = device_get_softc(dev); sc->sc_dev = dev; + sc->sc_domain = device_get_unit(dev); + + /* + * Get the physical memory region that is connected to the MD I/F + * of this SHub. It allows us to allocate memory that's close to + * this SHub. Fail the attach if we don't have local memory, as + * we really depend on it. + */ + tbl = ptr = acpi_find_table(ACPI_SIG_SRAT); + acpi_walk_subtables((uint8_t *)ptr + sizeof(ACPI_TABLE_SRAT), + (uint8_t *)ptr + tbl->Length, sgisn_shub_attach_srat_cb, dev); + if (sc->sc_memsize == 0) + return (ENXIO); + + if (bootverbose) + device_printf(dev, "%#lx bytes of attached memory at %#lx\n", + sc->sc_memsize, sc->sc_membase); + + /* + * Obtain our NASID. + */ + r = ia64_sal_entry(SAL_SGISN_SN_INFO, 0, 0, 0, 0, 0, 0, 0); + if (r.sal_status != 0) + return (ENXIO); + + sc->sc_hubtype = r.sal_result[0] & 0xff; + sc->sc_nasid_mask = r.sal_result[1] & 0xffff; + sc->sc_nasid_shft = (r.sal_result[1] >> 16) & 0xff; + sc->sc_nasid = (sc->sc_membase >> sc->sc_nasid_shft) & + sc->sc_nasid_mask; + + if (bootverbose) + device_printf(dev, "NASID=%#x\n", sc->sc_nasid); + + /* + * Allocate contiguous memory, local to the SHub, for collecting + * SHub information from the PROM and for discovering the PCI + * host controllers connected to the SHub. + */ + sc->sc_fwhub = contigmalloc(sizeof(struct sgisn_fwhub), M_DEVBUF, + M_ZERO, sc->sc_membase, sc->sc_membase + sc->sc_memsize, 16, 0); + + sc->sc_fwhub->hub_pci_maxseg = 0xffffffff; + sc->sc_fwhub->hub_pci_maxbus = 0xff; + r = ia64_sal_entry(SAL_SGISN_IOHUB_INFO, sc->sc_nasid, + ia64_tpa((uintptr_t)sc->sc_fwhub), 0, 0, 0, 0, 0); + if (r.sal_status != 0) { + contigfree(sc->sc_fwhub, sizeof(struct sgisn_fwhub), M_DEVBUF); + return (ENXIO); + } + + for (wdgt = 0; wdgt < SGISN_HUB_NWIDGETS; wdgt++) + sc->sc_fwhub->hub_widget[wdgt].wgt_hub = sc->sc_fwhub; + + r = ia64_sal_entry(SAL_SGISN_KLCONFIG_ADDR, sc->sc_nasid, + 0, 0, 0, 0, 0, 0); + device_printf(dev, "KLCONFIG: status=%#lx, addr=%#lx\n", + r.sal_status, r.sal_result[0]); + + /* + * XXX Hack to avoid having the same PCI busses as children of any + * SHub we have. The problem is that we can't pass the nasid to the + * the SAL function. So either we get all the busses, irrespective + * of the node in which they live or we always get the busses local + * to the CPU. I can't tell the difference, because I don't have + * busses on the other brick right now. + * In any case: we don't have a good way yet to figure out if the + * bus connects to the SHub in question. + */ + if (sc->sc_nasid != 0) + return (0); + + for (seg = 0; seg <= sc->sc_fwhub->hub_pci_maxseg; seg++) { + for (bus = 0; bus <= sc->sc_fwhub->hub_pci_maxbus; bus++) { + r = ia64_sal_entry(SAL_SGISN_IOBUS_INFO, seg, bus, + ia64_tpa((uintptr_t)&addr), 0, 0, 0, 0); + if (r.sal_status == 0 && addr != 0) { + child = device_add_child(dev, "pcib", -1); + device_set_ivars(child, (void *)(uintptr_t) + ((seg << 8) | (bus & 0xff))); + } + } + } - device_add_child(dev, "pci", -1); return (bus_generic_attach(dev)); } static int sgisn_shub_read_ivar(device_t dev, device_t child, int which, uintptr_t *res) { -// XXX struct sgisn_shub_softc *sc = device_get_softc(dev); + uintptr_t ivars; + ivars = (uintptr_t)device_get_ivars(child); + switch (which) { + case SHUB_IVAR_PCIBUS: + *res = ivars & 0xff; + return (0); + case SHUB_IVAR_PCISEG: + *res = ivars >> 8; + return (0); + } return (ENOENT); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103290036.p2T0aaGq011444>