Just decided to try installing FreeBSD/sparc64 on a Tatung U4MP The U4MP is a rackmount is based on the SUN SPARCengine UltraAXmp+ system board. This one has dual UltraSPARC II 450 MHz processors and 2048 MiB of RAM. I decided to netboot FreeBSD right from a CD image on a server, via OPB. Here's the log of the bootup with some POST output prior to kernel bootstrap: UltraAX-MP+ WorkServer (2 X UltraSPARC-II 448MHz), No Keyboard OpenBoot 3.10.50 ME, 2048 MB memory installed, Serial #15728707. Ethernet address 8:0:20:f0:0:43, Host ID: 80f00043. Initializing1024 megs of memory at addr 0 897 Software Power ON CPU0 has assumed the role of Boot CPU @(#) UltraAX-MP+ WorkServer 3.10.50 ME created 1999/09/13 14:38 Online: CPU0 UltraSPARC-II (v10.0) 5:1 4096KB 2-2 ECache MCap 10 Online: CPU1 UltraSPARC-II (v10.0) 5:1 4096KB 2-2 ECache MCap 10 Offline: CPU2 Offline: CPU3 Enter Checking KB ps/2 kbd check: 0000.0000.0000.00fe Checking Sun KB Marvin SC Dtag SRAM supports upto 8192KB of ECache Setting system ECache size to 4096KB Clearing DTAGS...Done Clearing E-Cache Tags...Done Clearing I/D TLBs...Done Probing Memory... memory @ 0000.0000.0000.0000 : 128 128 128 128 128 128 128 128 memory @ 0000.0000.4000.0000 : X X X X X X X X memory @ 0000.0000.8000.0000 : 128 128 128 128 128 128 128 128 memory @ 0000.0000.c000.0000 : X X X X X X X X Done MEM BASE = 0000.0000.8000.0000 MEM SIZE = 0000.0000.4000.0000 Clearing Memory...Done MMUs ON Copying ROM to RAM...Done ROM PC = 0000.01ff.f000.4730 Dcmpesig noMmry.000.00.00045a4 29KB..Doe Satn oth krel t00.00f057d ttya initialized SC Control: EWP:0 IAP:0 FATAL:0 WAKEUP:0 BXIR:0 BPOR:0 SXIR:0 SPOR:1 POR:0 Probing Memory Bank #0 128 128 128 128 128 128 128 128 : 1024 Megabytes Probing Memory Bank #1 0 0 0 0 0 0 0 0 : 0 Megabytes Probing Memory Bank #2 128 128 128 128 128 128 128 128 : 1024 Megabytes Probing Memory Bank #3 0 0 0 0 0 0 0 0 : 0 Megabytes Setting 60ns memory timings Environmental monitoring: Disabled i2c adc adc adc gpio gpio Probing Floppy: No drives detected Probing UPA slots... UPA slot 0 cpu UPA slot 1 cpu UPA slot 4 pci pci UPA slot 1f pci pci Probing /pci@1f,4000 at Device 1 network Probing /pci@1f,4000 at Device 2 Nothing there Probing /pci@1f,4000 at Device 3 Nothing there Probing /pci@1f,4000 at Device 4 Nothing there Probing /pci@1f,2000 at Device 1 Nothing there Probing /pci@4,4000 at Device 6 scsi disk tape scsi disk tape Probing /pci@4,4000 at Device 2 SUNW,m64Pro Probing /pci@4,4000 at Device 3 Nothing there Probing /pci@4,4000 at Device 4 Nothing there Probing /pci@4,4000 at Device 5 Nothing there Probing /pci@4,2000 at Device 1 Nothing there SC Control: EWP:0 IAP:0 FATAL:0 WAKEUP:0 BXIR:0 BPOR:0 SXIR:0 SPOR:1 POR:0 Probing Memory Bank #0 128 128 128 128 128 128 128 128 : 1024 Megabytes Probing Memory Bank #1 0 0 0 0 0 0 0 0 : 0 Megabytes Probing Memory Bank #2 128 128 128 128 128 128 128 128 : 1024 Megabytes Probing Memory Bank #3 0 0 0 0 0 0 0 0 : 0 Megabytes Setting 60ns memory timings Environmental monitoring: Disabled i2c adc adc adc gpio gpio Probing Floppy: No drives detected Probing UPA slots... UPA slot 0 cpu UPA slot 1 cpu UPA slot 4 pci pci UPA slot 1f pci pci Probing /pci@1f,4000 at Device 1 network Probing /pci@1f,4000 at Device 2 Nothing there Probing /pci@1f,4000 at Device 3 Nothing there Probing /pci@1f,4000 at Device 4 Nothing there Probing /pci@1f,2000 at Device 1 Nothing there Probing /pci@4,4000 at Device 6 scsi disk tape scsi disk tape Probing /pci@4,4000 at Device 2 SUNW,m64Pro Probing /pci@4,4000 at Device 3 Nothing there Probing /pci@4,4000 at Device 4 Nothing there Probing /pci@4,4000 at Device 5 Nothing there Probing /pci@4,2000 at Device 1 Nothing there UltraAX-MP+ WorkServer (2 X UltraSPARC-II 448MHz), No Keyboard OpenBoot 3.10.50 ME, 2048 MB memory installed, Serial #15728707. Ethernet address 8:0:20:f0:0:43, Host ID: 80f00043. Executing last command: boot /pci@1f,4000/network@1,1:bootp,loader-sparc64 Boot device: /pci@1f,4000/network@1,1:bootp,loader-sparc64 File and args: Using Onboard Transceiver - Link Up. 36a00 Server IP address: 10.101.1.1 Client IP address: 10.101.1.13 Gateway IP address: 10.101.1.1 Consoles: Open Firmware console Booting with sun4u support. FreeBSD/sparc64 bootstrap loader, Revision 1.0 (root@obrian.cse.buffalo.edu, Thu Jan 1 08:47:00 UTC 2009) bootpath="/pci@1f,4000/network@1,1:bootp,loader-sparc64" boot: ethernet address: 08:00:20:f0:00:43 Using Onboard Transceiver - Link Up. net_open: server addr: 10.101.1.1 net_open: server path: /mnt/cdrom Loading /boot/defaults/loader.conf /boot/kernel/kernel data=0x739b48+0x74b38 syms=[0x8+0x7d058+0x8+0x6bd34] - Hit [Enter] to boot immediately, or any other key for command prompt. Booting [/boot/kernel/kernel]... jumping to kernel entry at 0xc0070000. stray vector interrupt 2029 Copyright (c) 1992-2009 The FreeBSD Project. Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994 The Regents of the University of California. All rights reserved. FreeBSD is a registered trademark of The FreeBSD Foundation. FreeBSD 7.1-RELEASE #0: Fri Jan 2 01:32:39 UTC 2009 root@obrian.cse.buffalo.edu:/usr/obj/usr/src/sys/GENERIC real memory = 2147483648 (2048 MB) avail memory = 2075926528 (1979 MB) cpu0: Sun Microsystems UltraSparc-II Processor (448.00 MHz CPU) cpu1: Sun Microsystems UltraSparc-II Processor (448.00 MHz CPU) FreeBSD/SMP: Multiprocessor System Detected: 2 CPUs registered firmware set <isp_1000> registered firmware set <isp_1040> registered firmware set <isp_1040_it> registered firmware set <isp_1080> registered firmware set <isp_1080_it> registered firmware set <isp_12160> registered firmware set <isp_12160_it> registered firmware set <isp_2100> registered firmware set <isp_2200> registered firmware set <isp_2300> registered firmware set <isp_2322> registered firmware set <isp_2400> kbd0 at kbdmux0 ath_hal: 0.9.20.3 (AR5210, AR5211, AR5212, RF5111, RF5112, RF2413, RF5413, REGOP S_FUNC) nexus0: <Open Firmware Nexus device> pcib0: <U2P UPA-PCI bridge> mem 0x1fe00004000-0x1fe00005fff,0x1fe01000000-0x1fe0 10000ff,0x1fe00000000-0x1fe0000cfff irq 2033,2030,2031,2021,2024,2034 on nexus0 pcib0: Psycho, impl 0, version 4, IGN 0x1f, bus B, 33MHz pcib0: [FILTER] pcib0: [FILTER] pcib0: [GIANT-LOCKED] pcib0: [ITHREAD] pcib0: [GIANT-LOCKED] pcib0: [ITHREAD] initializing counter-timer Timecounter "pcib0" frequency 1000000 Hz quality 100 pcib0: DVMA map: 0xfc000000 to 0xffffffff pcib0: [FILTER] pci0: <OFW PCI bus> on pcib0 ebus0: <PCI-EBus2 bridge> mem 0x70000000-0x70ffffff,0x71000000-0x717fffff at dev ice 1.0 on pci0 auxio0: <Sun Auxiliary I/O> addr 0x1400726000-0x1400726003,0x1400728000-0x140072 8003,0x140072a000-0x140072a003,0x140072c000-0x140072c003,0x140072f000-0x140072f0 03 on ebus0 ebus0: <power> addr 0x1400724000-0x1400724003 irq 37 (no driver attached) ebus0: <SUNW,pll> addr 0x1400504000-0x1400504002 (no driver attached) ebus0: <sc> addr 0x1400500000-0x1400500007 (no driver attached) scc0: <Siemens SAB 82532 dual channel SCC> addr 0x1400400000-0x140040007f irq 43 on ebus0 scc0: [FILTER] uart0: <SAB 82532 v3.2, channel A> on scc0 uart0: [FILTER] uart0: CTS oflow uart0: console (9600,n,8,1) uart1: <SAB 82532 v3.2, channel B> on scc0 uart1: [FILTER] uart1: CTS oflow uart2: <16550 or compatible> addr 0x14003803f8-0x14003803ff irq 41 on ebus0 uart2: [FILTER] uart2: keyboard (1200,n,8,1) uart2: keyboard not present uart3: <16550 or compatible> addr 0x14003602f8-0x14003602ff irq 42 on ebus0 uart3: [FILTER] ebus0: <ecpp> addr 0x1400340278-0x1400340287,0x140030015c-0x140030015d,0x1400700 000-0x140070000f irq 34 (no driver attached) ebus0: <fdthree> addr 0x14003203f0-0x14003203f7,0x1400706000-0x140070600f,0x1400 720000-0x1400720003 irq 39 (no driver attached) eeprom0: <EEPROM/clock> addr 0x1400000000-0x1400001fff on ebus0 eeprom0: model mk48t59 ebus0: <flashprom> addr 0x1000000000-0x10000fffff (no driver attached) ebus0: <i2c> addr 0x1400600000-0x1400600003 irq 40 (no driver attached) hme0: <Sun HME 10/100 Ethernet> mem 0x8000-0xffff at device 1.1 on pci0 miibus0: <MII bus> on hme0 nsphy0: <DP83840 10/100 media interface> PHY 1 on miibus0 nsphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto hme0: Ethernet address: 08:00:20:f0:00:43 hme0: [ITHREAD] pcib1: <U2P UPA-PCI bridge> mem 0x1fe00002000-0x1fe00003fff,0x1fe01800000-0x1fe0 18000ff,0x1fe00000000-0x1fe0000cfff irq 2032,2030,2031,2021,2024,2034 on nexus0 pcib1: Psycho, impl 0, version 4, IGN 0x1f, bus A, 66MHz pcib1: [FILTER] pci1: <OFW PCI bus> on pcib1 pcib2: <U2P UPA-PCI bridge> mem 0x1c800004000-0x1c800005fff,0x1c801000000-0x1c80 10000ff,0x1c800000000-0x1c80000cfff irq 305,302,303 on nexus0 pcib2: Psycho, impl 0, version 4, IGN 0x4, bus B, 33MHz pcib2: [FILTER] pcib2: [FILTER] panic: psycho_set_intr: failed to set up interrupt 3 cpuid = 0 Uptime: 1s Automatic reboot in 15 seconds - press a key on the console to abort Rebooting... Resetting ... How-To-Repeat: It panics every single time on this model, however I've ever tried any other version, either. I'll be testing with NetBSD/sparc64 4.0 next and see how it does, as it looks like the psycho driver that FreeBSD uses was derived from NetBSD. Note that the system boots and runs just fine with the copy of Solaris 8 that's installed on one of the local drives.
On Wed, Feb 04, 2009 at 05:11:11PM +0000, Rory Arms wrote: > > pcib2: <U2P UPA-PCI bridge> mem 0x1c800004000-0x1c800005fff,0x1c801000000-0x1c80 > 10000ff,0x1c800000000-0x1c80000cfff irq 305,302,303 on nexus0 > pcib2: Psycho, impl 0, version 4, IGN 0x4, bus B, 33MHz > pcib2: [FILTER] > pcib2: [FILTER] > panic: psycho_set_intr: failed to set up interrupt 3 Could you please give the following stable/7 kernel a try? http://people.freebsd.org/~marius/psycho.gz It's built with the patch at: http://people.freebsd.org/~marius/psycho.diff Marius
State Changed From-To: open->feedback Note that submitter was asked for feedback.
Thanks, Marius. As mentioned in my reply email to you a few days ago, your patch resolves this issue. I look forward to seeing it committed to 7.1-STABLE. - rory
Author: marius Date: Thu Mar 19 20:52:46 2009 New Revision: 190109 URL: http://svn.freebsd.org/changeset/base/190109 Log: - Ensure we find no unexpected partner. - Failing to register as interrupt controller during attach shouldn't be fatal so just inform about this instead of panicing. - Disable rerun of the streaming cache as workaround for a silicon bug of certain Psycho versions. - Remove the comment regarding lack of newbus'ified bus_dma(9) as being able to associate a DMA tag with a device would allow to implement CDMA flushing/syncing in bus_dmamap_sync(9) but that would totally kill performance. Given that for devices not behind a PCI-PCI bridge the host-to-PCI bridges also only do CDMA flushing/syncing based on interrupts there's no additional disadvantage for polling(4) callbacks in the case schizo(4) has to do the CDMA flushing/syncing but rather a general problem. - Don't panic if the power failure, power management or over-temperature interrupts doesn't exist as these aren't mandatory and not available with all controllers (not even Psychos). [1] - Take advantage of KOBJMETHOD_END. - Remove some redundant variables. - Add missing const. PR: 131371 [1] Modified: head/sys/sparc64/pci/psycho.c head/sys/sparc64/pci/psychovar.h Modified: head/sys/sparc64/pci/psycho.c ============================================================================== --- head/sys/sparc64/pci/psycho.c Thu Mar 19 20:48:47 2009 (r190108) +++ head/sys/sparc64/pci/psycho.c Thu Mar 19 20:52:46 2009 (r190109) @@ -83,7 +83,7 @@ static void psycho_set_intr(struct psych driver_filter_t, driver_intr_t); static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *, bus_addr_t *, u_long *); -static driver_filter_t psycho_dmasync; +static driver_filter_t psycho_dma_sync_stub; static void psycho_intr_enable(void *); static void psycho_intr_disable(void *); static void psycho_intr_assign(void *); @@ -150,7 +150,7 @@ static device_method_t psycho_methods[] /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, psycho_get_node), - { 0, 0 } + KOBJMETHOD_END }; static devclass_t psycho_devclass; @@ -175,7 +175,7 @@ struct psycho_icarg { bus_addr_t pica_clr; }; -struct psycho_dmasync { +struct psycho_dma_sync { struct psycho_softc *pds_sc; driver_filter_t *pds_handler; /* handler to call */ void *pds_arg; /* argument for the handler */ @@ -232,14 +232,14 @@ struct psycho_desc { const char *pd_name; }; -static const struct psycho_desc psycho_compats[] = { +static const struct psycho_desc const psycho_compats[] = { { "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" }, { "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre compatible" }, { "pci108e,a001", PSYCHO_MODE_SABRE, "Hummingbird compatible" }, { NULL, 0, NULL } }; -static const struct psycho_desc psycho_models[] = { +static const struct psycho_desc const psycho_models[] = { { "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" }, { "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" }, { NULL, 0, NULL } @@ -296,8 +296,8 @@ psycho_attach(device_t dev) phandle_t child, node; uint32_t dvmabase, prop, prop_array[2]; int32_t rev; - u_int ver; - int i, n, nrange, rid; + u_int rerun, ver; + int i, n; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); @@ -315,7 +315,7 @@ psycho_attach(device_t dev) * (2) the shared Psycho configuration registers */ if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { - rid = 2; + i = 2; sc->sc_pcictl = bus_get_resource_start(dev, SYS_RES_MEMORY, 0) - bus_get_resource_start(dev, SYS_RES_MEMORY, 2); @@ -332,18 +332,18 @@ psycho_attach(device_t dev) /* NOTREACHED */ } } else { - rid = 0; + i = 0; sc->sc_pcictl = PSR_PCICTL0; sc->sc_half = 0; } - sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, (sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) | RF_ACTIVE); if (sc->sc_mem_res == NULL) panic("%s: could not allocate registers", __func__); /* - * Match other Psycho's that are already configured against + * Match other Psychos that are already configured against * the base physical address. This will be the same for a * pair of devices that share register space. */ @@ -363,6 +363,8 @@ psycho_attach(device_t dev) panic("%s: could not malloc mutex", __func__); mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN); } else { + if (sc->sc_mode != PSYCHO_MODE_PSYCHO) + panic("%s: no partner expected", __func__); if (mtx_initialized(osc->sc_mtx) == 0) panic("%s: mutex not initialized", __func__); sc->sc_mtx = osc->sc_mtx; @@ -408,16 +410,17 @@ psycho_attach(device_t dev) case 0: dr |= DIAG_RTRY_DIS; dr &= ~DIAG_DWSYNC_DIS; - /* XXX need to also disable rerun of the streaming buffers. */ + rerun = 0; break; case 1: csr &= ~PCICTL_ARB_PARK; dr |= DIAG_RTRY_DIS | DIAG_DWSYNC_DIS; - /* XXX need to also disable rerun of the streaming buffers. */ + rerun = 0; break; default: dr |= DIAG_DWSYNC_DIS; dr &= ~DIAG_RTRY_DIS; + rerun = 1; break; } @@ -460,13 +463,12 @@ psycho_attach(device_t dev) rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0) panic("%s: failed to set up memory rman", __func__); - nrange = OF_getprop_alloc(node, "ranges", sizeof(*range), - (void **)&range); + n = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range); /* * Make sure that the expected ranges are present. The * OFW_PCI_CS_MEM64 one is not currently used though. */ - if (nrange != PSYCHO_NRANGE) + if (n != PSYCHO_NRANGE) panic("%s: unsupported number of ranges", __func__); /* * Find the addresses of the various bus spaces. @@ -493,7 +495,8 @@ psycho_attach(device_t dev) /* * Hunt through all the interrupt mapping regs and register * our interrupt controller for the corresponding interrupt - * vectors. + * vectors. We do this early in order to be able to catch + * stray interrupts. */ for (n = 0; n <= PSYCHO_MAX_INO; n++) { if (psycho_find_intrmap(sc, n, &intrmap, &intrclr, @@ -523,22 +526,23 @@ psycho_attach(device_t dev) INTMAP_ENABLE(INTMAP_VEC(sc->sc_ign, n), PCPU_GET(mid))); #endif - if (intr_controller_register(INTMAP_VEC(sc->sc_ign, n), - &psycho_ic, pica) != 0) - panic("%s: could not register interrupt " - "controller for INO %d", __func__, n); + i = intr_controller_register(INTMAP_VEC(sc->sc_ign, n), + &psycho_ic, pica); + if (i != 0) + device_printf(dev, "could not register " + "interrupt controller for INO %d (%d)\n", + n, i); } - if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { - /* Initialize the counter-timer. */ + if (sc->sc_mode == PSYCHO_MODE_PSYCHO) sparc64_counter_init(device_get_nameunit(dev), rman_get_bustag(sc->sc_mem_res), rman_get_bushandle(sc->sc_mem_res), PSR_TC0); - } /* * Set up IOMMU and PCI configuration if we're the first - * of a pair of Psycho's to arrive here. + * of a pair of Psychos to arrive here or a Hummingbird + * or Sabre. * * We should calculate a TSB size based on amount of RAM * and number of bus controllers and number and type of @@ -556,10 +560,10 @@ psycho_attach(device_t dev) else sc->sc_is->is_pmaxaddr = IOMMU_MAXADDR(PSYCHO_IOMMU_BITS); - sc->sc_is->is_sb[0] = 0; - sc->sc_is->is_sb[1] = 0; + sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0; if (OF_getproplen(node, "no-streaming-cache") < 0) sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF; + sc->sc_is->is_flags |= (rerun != 1) ? IOMMU_RERUN_DISABLE : 0; psycho_iommu_init(sc, 3, dvmabase); } else { /* Just copy IOMMU state, config tag and address. */ @@ -694,12 +698,20 @@ psycho_set_intr(struct psycho_softc *sc, rid = index; sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &rid, RF_ACTIVE); + if (sc->sc_irq_res[index] == NULL && intrmap >= PSR_POWER_INT_MAP) { + /* + * These interrupts aren't mandatory and not available + * with all controllers (not even Psychos). + */ + return; + } if (sc->sc_irq_res[index] == NULL || INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign || INTVEC(PSYCHO_READ8(sc, intrmap)) != vec || intr_vectors[vec].iv_ic != &psycho_ic || - bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC, - filt, intr, sc, &sc->sc_ihand[index]) != 0) + bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], + INTR_TYPE_MISC | INTR_FAST, filt, intr, sc, + &sc->sc_ihand[index]) != 0) panic("%s: failed to set up interrupt %d", __func__, index); } @@ -1065,9 +1077,9 @@ psycho_read_ivar(device_t dev, device_t } static int -psycho_dmasync(void *arg) +psycho_dma_sync_stub(void *arg) { - struct psycho_dmasync *pds = arg; + struct psycho_dma_sync *pds = arg; (void)PCIB_READ_CONFIG(pds->pds_ppb, pds->pds_bus, pds->pds_slot, pds->pds_func, PCIR_VENDOR, 2); @@ -1125,7 +1137,7 @@ psycho_setup_intr(device_t dev, device_t devclass_t pci_devclass; device_t cdev, pdev, pcidev; struct psycho_softc *sc; - struct psycho_dmasync *pds; + struct psycho_dma_sync *pds; u_long vec; int error; @@ -1142,17 +1154,12 @@ psycho_setup_intr(device_t dev, device_t } /* - * The Sabre-APB-combination has a bug where it does not drain - * DMA write data for devices behind additional PCI-PCI bridges - * underneath the APB PCI-PCI bridge. The workaround is to do - * a read on the farest PCI-PCI bridge followed by a read of the - * PCI DMA write sync register of the Sabre. - * XXX installing the wrapper for an affected device and the - * actual workaround in psycho_dmasync() should be moved to - * psycho(4)-specific bus_dma_tag_create() and bus_dmamap_sync() - * methods, respectively, once DMA tag creation is newbus'ified, - * so the workaround isn't only applied for interrupt handlers - * but also for polling(4) callbacks. + * The Sabre-APB-combination does not automatically flush DMA + * write data for devices behind additional PCI-PCI bridges + * underneath the APB PCI-PCI bridge. The procedure for a + * manual flush is to do a PIO read on the far side of the + * farthest PCI-PCI bridge followed by a read of the PCI DMA + * write sync register of the Sabre. */ if (sc->sc_mode == PSYCHO_MODE_SABRE) { pds = malloc(sizeof(*pds), M_DEVBUF, M_NOWAIT | M_ZERO); @@ -1191,20 +1198,20 @@ psycho_setup_intr(device_t dev, device_t pds->pds_func = pci_get_function(pcidev); if (bootverbose) device_printf(dev, "installed DMA sync " - "workaround for device %d.%d on bus %d\n", + "wrapper for device %d.%d on bus %d\n", pds->pds_slot, pds->pds_func, pds->pds_bus); if (intr == NULL) { pds->pds_handler = filt; error = bus_generic_setup_intr(dev, child, - ires, flags, psycho_dmasync, intr, pds, - cookiep); + ires, flags, psycho_dma_sync_stub, intr, + pds, cookiep); } else { pds->pds_handler = (driver_filter_t *)intr; error = bus_generic_setup_intr(dev, child, ires, flags, filt, - (driver_intr_t *)psycho_dmasync, pds, - cookiep); + (driver_intr_t *)psycho_dma_sync_stub, + pds, cookiep); } } else error = bus_generic_setup_intr(dev, child, ires, @@ -1226,7 +1233,7 @@ psycho_teardown_intr(device_t dev, devic void *cookie) { struct psycho_softc *sc; - struct psycho_dmasync *pds; + struct psycho_dma_sync *pds; int error; sc = device_get_softc(dev); @@ -1314,8 +1321,8 @@ psycho_activate_resource(device_t bus, d type, rid, r)); if (type == SYS_RES_MEMORY) { /* - * Need to memory-map the device space, as some drivers depend - * on the virtual address being set and useable. + * Need to memory-map the device space, as some drivers + * depend on the virtual address being set and usable. */ error = sparc64_bus_mem_map(rman_get_bustag(r), rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); Modified: head/sys/sparc64/pci/psychovar.h ============================================================================== --- head/sys/sparc64/pci/psychovar.h Thu Mar 19 20:48:47 2009 (r190108) +++ head/sys/sparc64/pci/psychovar.h Thu Mar 19 20:52:46 2009 (r190109) @@ -49,8 +49,8 @@ struct psycho_softc { phandle_t sc_node; /* Firmware node */ u_int sc_mode; -#define PSYCHO_MODE_SABRE 1 -#define PSYCHO_MODE_PSYCHO 2 +#define PSYCHO_MODE_SABRE 0 +#define PSYCHO_MODE_PSYCHO 1 /* Bus A or B of a psycho pair? */ u_int sc_half; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
Author: marius Date: Sun Mar 22 21:38:24 2009 New Revision: 190290 URL: http://svn.freebsd.org/changeset/base/190290 Log: MFC: r190109 - Ensure we find no unexpected partner. - Failing to register as interrupt controller during attach shouldn't be fatal so just inform about this instead of panicing. - Disable rerun of the streaming cache as workaround for a silicon bug of certain Psycho versions. - Remove the comment regarding lack of newbus'ified bus_dma(9) as being able to associate a DMA tag with a device would allow to implement CDMA flushing/syncing in bus_dmamap_sync(9) but that would totally kill performance. Given that for devices not behind a PCI-PCI bridge the host-to-PCI bridges also only do CDMA flushing/syncing based on interrupts there's no additional disadvantage for polling(4) callbacks in the case schizo(4) has to do the CDMA flushing/syncing but rather a general problem. - Don't panic if the power failure, power management or over-temperature interrupts doesn't exist as these aren't mandatory and not available with all controllers (not even Psychos). [1] - Take advantage of KOBJMETHOD_END. - Remove some redundant variables. - Add missing const. PR: 131371 [1] Modified: stable/7/sys/ (props changed) stable/7/sys/contrib/pf/ (props changed) stable/7/sys/dev/ath/ath_hal/ (props changed) stable/7/sys/dev/cxgb/ (props changed) stable/7/sys/sparc64/pci/psycho.c stable/7/sys/sparc64/pci/psychovar.h Modified: stable/7/sys/sparc64/pci/psycho.c ============================================================================== --- stable/7/sys/sparc64/pci/psycho.c Sun Mar 22 21:31:02 2009 (r190289) +++ stable/7/sys/sparc64/pci/psycho.c Sun Mar 22 21:38:24 2009 (r190290) @@ -84,7 +84,7 @@ static void psycho_set_intr(struct psych driver_filter_t, driver_intr_t); static int psycho_find_intrmap(struct psycho_softc *, u_int, bus_addr_t *, bus_addr_t *, u_long *); -static driver_filter_t psycho_dmasync; +static driver_filter_t psycho_dma_sync_stub; static void psycho_intr_enable(void *); static void psycho_intr_disable(void *); static void psycho_intr_assign(void *); @@ -151,7 +151,7 @@ static device_method_t psycho_methods[] /* ofw_bus interface */ DEVMETHOD(ofw_bus_get_node, psycho_get_node), - { 0, 0 } + KOBJMETHOD_END }; static devclass_t psycho_devclass; @@ -176,7 +176,7 @@ struct psycho_icarg { bus_addr_t pica_clr; }; -struct psycho_dmasync { +struct psycho_dma_sync { struct psycho_softc *pds_sc; driver_filter_t *pds_handler; /* handler to call */ void *pds_arg; /* argument for the handler */ @@ -233,14 +233,14 @@ struct psycho_desc { const char *pd_name; }; -static const struct psycho_desc psycho_compats[] = { +static const struct psycho_desc const psycho_compats[] = { { "pci108e,8000", PSYCHO_MODE_PSYCHO, "Psycho compatible" }, { "pci108e,a000", PSYCHO_MODE_SABRE, "Sabre compatible" }, { "pci108e,a001", PSYCHO_MODE_SABRE, "Hummingbird compatible" }, { NULL, 0, NULL } }; -static const struct psycho_desc psycho_models[] = { +static const struct psycho_desc const psycho_models[] = { { "SUNW,psycho", PSYCHO_MODE_PSYCHO, "Psycho" }, { "SUNW,sabre", PSYCHO_MODE_SABRE, "Sabre" }, { NULL, 0, NULL } @@ -297,8 +297,8 @@ psycho_attach(device_t dev) phandle_t child, node; uint32_t dvmabase, prop, prop_array[2]; int32_t rev; - u_int ver; - int i, n, nrange, rid; + u_int rerun, ver; + int i, n; node = ofw_bus_get_node(dev); sc = device_get_softc(dev); @@ -316,7 +316,7 @@ psycho_attach(device_t dev) * (2) the shared Psycho configuration registers */ if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { - rid = 2; + i = 2; sc->sc_pcictl = bus_get_resource_start(dev, SYS_RES_MEMORY, 0) - bus_get_resource_start(dev, SYS_RES_MEMORY, 2); @@ -333,18 +333,18 @@ psycho_attach(device_t dev) /* NOTREACHED */ } } else { - rid = 0; + i = 0; sc->sc_pcictl = PSR_PCICTL0; sc->sc_half = 0; } - sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, + sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &i, (sc->sc_mode == PSYCHO_MODE_PSYCHO ? RF_SHAREABLE : 0) | RF_ACTIVE); if (sc->sc_mem_res == NULL) panic("%s: could not allocate registers", __func__); /* - * Match other Psycho's that are already configured against + * Match other Psychos that are already configured against * the base physical address. This will be the same for a * pair of devices that share register space. */ @@ -364,6 +364,8 @@ psycho_attach(device_t dev) panic("%s: could not malloc mutex", __func__); mtx_init(sc->sc_mtx, "pcib_mtx", NULL, MTX_SPIN); } else { + if (sc->sc_mode != PSYCHO_MODE_PSYCHO) + panic("%s: no partner expected", __func__); if (mtx_initialized(osc->sc_mtx) == 0) panic("%s: mutex not initialized", __func__); sc->sc_mtx = osc->sc_mtx; @@ -409,16 +411,17 @@ psycho_attach(device_t dev) case 0: dr |= DIAG_RTRY_DIS; dr &= ~DIAG_DWSYNC_DIS; - /* XXX need to also disable rerun of the streaming buffers. */ + rerun = 0; break; case 1: csr &= ~PCICTL_ARB_PARK; dr |= DIAG_RTRY_DIS | DIAG_DWSYNC_DIS; - /* XXX need to also disable rerun of the streaming buffers. */ + rerun = 0; break; default: dr |= DIAG_DWSYNC_DIS; dr &= ~DIAG_RTRY_DIS; + rerun = 1; break; } @@ -461,13 +464,12 @@ psycho_attach(device_t dev) rman_manage_region(&sc->sc_pci_mem_rman, 0, PSYCHO_MEM_SIZE) != 0) panic("%s: failed to set up memory rman", __func__); - nrange = OF_getprop_alloc(node, "ranges", sizeof(*range), - (void **)&range); + n = OF_getprop_alloc(node, "ranges", sizeof(*range), (void **)&range); /* * Make sure that the expected ranges are present. The * OFW_PCI_CS_MEM64 one is not currently used though. */ - if (nrange != PSYCHO_NRANGE) + if (n != PSYCHO_NRANGE) panic("%s: unsupported number of ranges", __func__); /* * Find the addresses of the various bus spaces. @@ -494,7 +496,8 @@ psycho_attach(device_t dev) /* * Hunt through all the interrupt mapping regs and register * our interrupt controller for the corresponding interrupt - * vectors. + * vectors. We do this early in order to be able to catch + * stray interrupts. */ for (n = 0; n <= PSYCHO_MAX_INO; n++) { if (psycho_find_intrmap(sc, n, &intrmap, &intrclr, @@ -524,22 +527,23 @@ psycho_attach(device_t dev) INTMAP_ENABLE(INTMAP_VEC(sc->sc_ign, n), PCPU_GET(mid))); #endif - if (intr_controller_register(INTMAP_VEC(sc->sc_ign, n), - &psycho_ic, pica) != 0) - panic("%s: could not register interrupt " - "controller for INO %d", __func__, n); + i = intr_controller_register(INTMAP_VEC(sc->sc_ign, n), + &psycho_ic, pica); + if (i != 0) + device_printf(dev, "could not register " + "interrupt controller for INO %d (%d)\n", + n, i); } - if (sc->sc_mode == PSYCHO_MODE_PSYCHO) { - /* Initialize the counter-timer. */ + if (sc->sc_mode == PSYCHO_MODE_PSYCHO) sparc64_counter_init(device_get_nameunit(dev), rman_get_bustag(sc->sc_mem_res), rman_get_bushandle(sc->sc_mem_res), PSR_TC0); - } /* * Set up IOMMU and PCI configuration if we're the first - * of a pair of Psycho's to arrive here. + * of a pair of Psychos to arrive here or a Hummingbird + * or Sabre. * * We should calculate a TSB size based on amount of RAM * and number of bus controllers and number and type of @@ -557,10 +561,10 @@ psycho_attach(device_t dev) else sc->sc_is->is_pmaxaddr = IOMMU_MAXADDR(PSYCHO_IOMMU_BITS); - sc->sc_is->is_sb[0] = 0; - sc->sc_is->is_sb[1] = 0; + sc->sc_is->is_sb[0] = sc->sc_is->is_sb[1] = 0; if (OF_getproplen(node, "no-streaming-cache") < 0) sc->sc_is->is_sb[0] = sc->sc_pcictl + PCR_STRBUF; + sc->sc_is->is_flags |= (rerun != 1) ? IOMMU_RERUN_DISABLE : 0; psycho_iommu_init(sc, 3, dvmabase); } else { /* Just copy IOMMU state, config tag and address. */ @@ -695,12 +699,20 @@ psycho_set_intr(struct psycho_softc *sc, rid = index; sc->sc_irq_res[index] = bus_alloc_resource_any(sc->sc_dev, SYS_RES_IRQ, &rid, RF_ACTIVE); + if (sc->sc_irq_res[index] == NULL && intrmap >= PSR_POWER_INT_MAP) { + /* + * These interrupts aren't mandatory and not available + * with all controllers (not even Psychos). + */ + return; + } if (sc->sc_irq_res[index] == NULL || INTIGN(vec = rman_get_start(sc->sc_irq_res[index])) != sc->sc_ign || INTVEC(PSYCHO_READ8(sc, intrmap)) != vec || intr_vectors[vec].iv_ic != &psycho_ic || - bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], INTR_TYPE_MISC, - filt, intr, sc, &sc->sc_ihand[index]) != 0) + bus_setup_intr(sc->sc_dev, sc->sc_irq_res[index], + INTR_TYPE_MISC | INTR_FAST, filt, intr, sc, + &sc->sc_ihand[index]) != 0) panic("%s: failed to set up interrupt %d", __func__, index); } @@ -1066,9 +1078,9 @@ psycho_read_ivar(device_t dev, device_t } static int -psycho_dmasync(void *arg) +psycho_dma_sync_stub(void *arg) { - struct psycho_dmasync *pds = arg; + struct psycho_dma_sync *pds = arg; (void)PCIB_READ_CONFIG(pds->pds_ppb, pds->pds_bus, pds->pds_slot, pds->pds_func, PCIR_VENDOR, 2); @@ -1126,7 +1138,7 @@ psycho_setup_intr(device_t dev, device_t devclass_t pci_devclass; device_t cdev, pdev, pcidev; struct psycho_softc *sc; - struct psycho_dmasync *pds; + struct psycho_dma_sync *pds; u_long vec; int error; @@ -1143,17 +1155,12 @@ psycho_setup_intr(device_t dev, device_t } /* - * The Sabre-APB-combination has a bug where it does not drain - * DMA write data for devices behind additional PCI-PCI bridges - * underneath the APB PCI-PCI bridge. The workaround is to do - * a read on the farest PCI-PCI bridge followed by a read of the - * PCI DMA write sync register of the Sabre. - * XXX installing the wrapper for an affected device and the - * actual workaround in psycho_dmasync() should be moved to - * psycho(4)-specific bus_dma_tag_create() and bus_dmamap_sync() - * methods, respectively, once DMA tag creation is newbus'ified, - * so the workaround isn't only applied for interrupt handlers - * but also for polling(4) callbacks. + * The Sabre-APB-combination does not automatically flush DMA + * write data for devices behind additional PCI-PCI bridges + * underneath the APB PCI-PCI bridge. The procedure for a + * manual flush is to do a PIO read on the far side of the + * farthest PCI-PCI bridge followed by a read of the PCI DMA + * write sync register of the Sabre. */ if (sc->sc_mode == PSYCHO_MODE_SABRE) { pds = malloc(sizeof(*pds), M_DEVBUF, M_NOWAIT | M_ZERO); @@ -1192,20 +1199,20 @@ psycho_setup_intr(device_t dev, device_t pds->pds_func = pci_get_function(pcidev); if (bootverbose) device_printf(dev, "installed DMA sync " - "workaround for device %d.%d on bus %d\n", + "wrapper for device %d.%d on bus %d\n", pds->pds_slot, pds->pds_func, pds->pds_bus); if (intr == NULL) { pds->pds_handler = filt; error = bus_generic_setup_intr(dev, child, - ires, flags, psycho_dmasync, intr, pds, - cookiep); + ires, flags, psycho_dma_sync_stub, intr, + pds, cookiep); } else { pds->pds_handler = (driver_filter_t *)intr; error = bus_generic_setup_intr(dev, child, ires, flags, filt, - (driver_intr_t *)psycho_dmasync, pds, - cookiep); + (driver_intr_t *)psycho_dma_sync_stub, + pds, cookiep); } } else error = bus_generic_setup_intr(dev, child, ires, @@ -1227,7 +1234,7 @@ psycho_teardown_intr(device_t dev, devic void *cookie) { struct psycho_softc *sc; - struct psycho_dmasync *pds; + struct psycho_dma_sync *pds; int error; sc = device_get_softc(dev); @@ -1315,8 +1322,8 @@ psycho_activate_resource(device_t bus, d type, rid, r)); if (type == SYS_RES_MEMORY) { /* - * Need to memory-map the device space, as some drivers depend - * on the virtual address being set and useable. + * Need to memory-map the device space, as some drivers + * depend on the virtual address being set and usable. */ error = sparc64_bus_mem_map(rman_get_bustag(r), rman_get_bushandle(r), rman_get_size(r), 0, 0, &p); Modified: stable/7/sys/sparc64/pci/psychovar.h ============================================================================== --- stable/7/sys/sparc64/pci/psychovar.h Sun Mar 22 21:31:02 2009 (r190289) +++ stable/7/sys/sparc64/pci/psychovar.h Sun Mar 22 21:38:24 2009 (r190290) @@ -49,8 +49,8 @@ struct psycho_softc { phandle_t sc_node; /* Firmware node */ u_int sc_mode; -#define PSYCHO_MODE_SABRE 1 -#define PSYCHO_MODE_PSYCHO 2 +#define PSYCHO_MODE_SABRE 0 +#define PSYCHO_MODE_PSYCHO 1 /* Bus A or B of a psycho pair? */ u_int sc_half; _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscribe@freebsd.org"
State Changed From-To: feedback->closed close