Subject: Re: 4.99.51 kernel crashes while detecting a PCI card
To: Martin Husemann <martin@duskware.de>
From: Matthias Scheler <tron@zhadum.org.uk>
List: port-sparc64
Date: 02/02/2008 11:58:08
On Sat, Feb 02, 2008 at 10:55:02AM +0000, Matthias Scheler wrote:
> And here is what "gdb" found:
> 
> (gdb) list *(config_attach_loc+0x158)
> 0x1221798 is in config_attach_loc (/src/NetBSD-current/src/sys/kern/subr_autoconf.c:1276).
> 1271
> 1272    #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
> 1273            if (splash_progress_state)
> 1274                    splash_progress_update(splash_progress_state);
> 1275    #endif
> 1276            (*dev->dv_cfattach->ca_attach)(parent, dev, aux);
> 1277    #if defined(SPLASHSCREEN) && defined(SPLASHSCREEN_PROGRESS)
> 1278            if (splash_progress_state)
> 1279                    splash_progress_update(splash_progress_state);
> 1280    #endif

I realized that the backtrace didn't give the right function. Here is
what disassembling at the report instruction pointer prints out:

0x12eac60 is in pci_conf_read (/src/NetBSD-current/src/sys/arch/sparc64/dev/pci_machdep.c:379).
374     /* assume we are mapped little-endian/side-effect */
375     pcireg_t
376     pci_conf_read(pci_chipset_tag_t pc, pcitag_t tag, int reg)
377     {
378             struct psycho_pbm *pp = pc->cookie;
379             struct psycho_softc *sc = pp->pp_sc;
380             pcireg_t val = (pcireg_t)~0;
381     
382             DPRINTF(SPDB_CONF, ("pci_conf_read: tag %lx reg %x ", 
383                     (long)tag, reg));

I've chaned the code to ...

	struct psycho_pbm *pp;
	struct psycho_softc *sc;
	pcireg_t val = (pcireg_t)~0;

	KASSERT(pc != NULL);
	pp = pc->cookie;
	KASSERT(pp != NULL);
	sc = pp->pp_sc;

... and got this panic:

pci1 at psycho1
bge0 at pci1 dev 1 function 0: Broadcom BCM5701 Gigabit Ethernet
panic: kernel diagnostic assertion "pc != NULL" failed: file "/src/NetBSD-current/src/sys/arch/sparc64/dev/pci_machdep.c", line 387

cpu0: kdb breakpoint at 134a100
Stopped in pid 0.1 (system) at  netbsd:cpu_Debugger+0x4:        nop
db> bt
__kernassert(1473b88, 14c80f0, 183, 149bc80, 0, 0) at netbsd:__kernassert+0x2c
pci_conf_read(0, f0088f1400800800, 4, 0, 3559320, 3559340) at netbsd:pci_conf_read+0x84
bge_attach(3ab9000, 3aacd00, 1c05358, 1810800, 1813000, 2) at netbsd:bge_attach+0x74
config_attach_loc(3aacd00, 1808c28, 1c053bc, 1c05358, 1, 12ed0e0) at netbsd:config_attach_loc+0x164
pci_probe_device(0, f0088f1400800800, 0, 0, 0, 0) at netbsd:pci_probe_device+0x254
sparc64_pci_enumerate_bus(3ab9000, 13cd990, 0, 42, 40, 181cc00) at netbsd:sparc64_pci_enumerate_bus+0x35c
pcirescan(0, 1472fa8, 13cd990, 3ab9037, 0, 3ab9037) at netbsd:pcirescan+0x44
pciattach(0, 3ab9000, 1c057d8, 1810800, 1813000, 2) at netbsd:pciattach+0x14c
config_attach_loc(3ab9000, 1808b08, 0, 1c057d8, 1, 13100c0) at netbsd:config_attach_loc+0x164
psycho_attach(3aadf00, 3aaa200, 1c059f0, 1810800, 1813000, 2) at netbsd:psycho_attach+0x4f8
config_attach_loc(3aaa200, 1808ad8, 0, 1c059f0, 1, 133bca0) at netbsd:config_attach_loc+0x164
mainbus_attach(0, 3aadf00, 0, 1810800, 1479400, 133bc00) at netbsd:mainbus_attach+0x474
config_attach_loc(3aadf00, 1808898, 0, 0, 1, 7) at netbsd:config_attach_loc+0x16

The call in bge_attach() looks like this:

static void
bge_attach(device_t parent, device_t self, void *aux)
{
        struct bge_softc        *sc = device_private(self);
[...]
        pci_chipset_tag_t       pc = sc->sc_pc;
[...]
	sc->sc_pc = pa->pa_pc;
[...]
	command = pci_conf_read(pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
[...]
}

The following patch avoids the panic:

Index: sys/dev/pci/if_bge.c
===================================================================
RCS file: /cvsroot/src/sys/dev/pci/if_bge.c,v
retrieving revision 1.142
diff -u -r1.142 if_bge.c
--- sys/dev/pci/if_bge.c	19 Jan 2008 22:10:18 -0000	1.142
+++ sys/dev/pci/if_bge.c	2 Feb 2008 11:57:36 -0000
@@ -2412,7 +2412,7 @@
 	struct pci_attach_args	*pa = aux;
 	const struct bge_product *bp;
 	const struct bge_revision *br;
-	pci_chipset_tag_t	pc = sc->sc_pc;
+	pci_chipset_tag_t	pc;
 	pci_intr_handle_t	ih;
 	const char		*intrstr = NULL;
 	bus_dma_segment_t	seg;
@@ -2442,6 +2442,7 @@
 	 * Map control/status registers.
 	 */
 	DPRINTFN(5, ("Map control/status regs\n"));
+	pc = sc->sc_pc;
 	command = pci_conf_read(pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG);
 	command |= PCI_COMMAND_MEM_ENABLE | PCI_COMMAND_MASTER_ENABLE;
 	pci_conf_write(pc, sc->sc_pcitag, PCI_COMMAND_STATUS_REG, command);

Does this look correct?

	Kind regards

-- 
Matthias Scheler                                  http://zhadum.org.uk/