Module Name:    src
Committed By:   riastradh
Date:           Sat Aug  4 03:55:44 UTC 2012

Modified Files:
        src/sys/dev/cardbus: fwohci_cardbus.c
        src/sys/dev/ieee1394: firewire.c firewirereg.h fwohci.c fwohcivar.h
        src/sys/dev/pci: fwohci_pci.c

Log Message:
Fix error branches and config pending races in firewire init.

This way, if anything fails, it just fails; you don't panic.  This can
happen if suspending and resuming of firewire is broken (e.g., as I
encountered in PR kern/44581).


To generate a diff of this commit:
cvs rdiff -u -r1.34 -r1.35 src/sys/dev/cardbus/fwohci_cardbus.c
cvs rdiff -u -r1.39 -r1.40 src/sys/dev/ieee1394/firewire.c
cvs rdiff -u -r1.17 -r1.18 src/sys/dev/ieee1394/firewirereg.h
cvs rdiff -u -r1.132 -r1.133 src/sys/dev/ieee1394/fwohci.c
cvs rdiff -u -r1.33 -r1.34 src/sys/dev/ieee1394/fwohcivar.h
cvs rdiff -u -r1.40 -r1.41 src/sys/dev/pci/fwohci_pci.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/cardbus/fwohci_cardbus.c
diff -u src/sys/dev/cardbus/fwohci_cardbus.c:1.34 src/sys/dev/cardbus/fwohci_cardbus.c:1.35
--- src/sys/dev/cardbus/fwohci_cardbus.c:1.34	Mon Aug  1 11:20:27 2011
+++ src/sys/dev/cardbus/fwohci_cardbus.c	Sat Aug  4 03:55:43 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: fwohci_cardbus.c,v 1.34 2011/08/01 11:20:27 drochner Exp $	*/
+/*	$NetBSD: fwohci_cardbus.c,v 1.35 2012/08/04 03:55:43 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fwohci_cardbus.c,v 1.34 2011/08/01 11:20:27 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fwohci_cardbus.c,v 1.35 2012/08/04 03:55:43 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -98,6 +98,8 @@ fwohci_cardbus_attach(device_t parent, d
 	       PCI_REVISION(ca->ca_class));
 	aprint_naive("\n");
 
+	fwohci_init(&sc->sc_sc);
+
 	/* Map I/O registers */
 	if (Cardbus_mapreg_map(ct, PCI_OHCI_MAP_REGISTER,
 	      PCI_MAPREG_TYPE_MEM, 0,
@@ -128,7 +130,7 @@ fwohci_cardbus_attach(device_t parent, d
 	}
 
 	/* XXX NULL should be replaced by some call to Cardbus coed */
-	if (fwohci_init(&sc->sc_sc) != 0) {
+	if (fwohci_attach(&sc->sc_sc) != 0) {
 		Cardbus_intr_disestablish(ct, sc->sc_ih);
 		sc->sc_ih = NULL;
 	}

Index: src/sys/dev/ieee1394/firewire.c
diff -u src/sys/dev/ieee1394/firewire.c:1.39 src/sys/dev/ieee1394/firewire.c:1.40
--- src/sys/dev/ieee1394/firewire.c:1.39	Sun Apr 29 18:31:40 2012
+++ src/sys/dev/ieee1394/firewire.c	Sat Aug  4 03:55:43 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: firewire.c,v 1.39 2012/04/29 18:31:40 dsl Exp $	*/
+/*	$NetBSD: firewire.c,v 1.40 2012/08/04 03:55:43 riastradh Exp $	*/
 /*-
  * Copyright (c) 2003 Hidetoshi Shimokawa
  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
@@ -37,7 +37,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.39 2012/04/29 18:31:40 dsl Exp $");
+__KERNEL_RCSID(0, "$NetBSD: firewire.c,v 1.40 2012/08/04 03:55:43 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -259,7 +259,6 @@ firewireattach(device_t parent, device_t
 	if (kthread_create(PRI_NONE, KTHREAD_MPSAFE, NULL, fw_bus_probe_thread,
 	    fc, &fc->probe_thread, "fw%dprobe", device_unit(fc->bdev)))
 		aprint_error_dev(self, "kthread_create failed\n");
-	config_pending_incr();
 
 	devlist = malloc(sizeof(struct firewire_dev_list), M_DEVBUF, M_NOWAIT);
 	if (devlist == NULL) {
@@ -679,6 +678,15 @@ fw_init(struct firewire_comm *fc)
 	fc->crom_src_buf = NULL;
 }
 
+void
+fw_destroy(struct firewire_comm *fc)
+{
+	mutex_destroy(&fc->arq->q_mtx);
+	mutex_destroy(&fc->ars->q_mtx);
+	mutex_destroy(&fc->atq->q_mtx);
+	mutex_destroy(&fc->ats->q_mtx);
+}
+
 #define BIND_CMP(addr, fwb) \
 	(((addr) < (fwb)->start) ? -1 : ((fwb)->end < (addr)) ? 1 : 0)
 
@@ -1935,8 +1943,6 @@ fw_bus_probe_thread(void *arg)
 {
 	struct firewire_comm *fc = (struct firewire_comm *)arg;
 
-	config_pending_decr();
-
 	mutex_enter(&fc->wait_lock);
 	while (fc->status != FWBUSDETACH) {
 		if (fc->status == FWBUSEXPLORE) {

Index: src/sys/dev/ieee1394/firewirereg.h
diff -u src/sys/dev/ieee1394/firewirereg.h:1.17 src/sys/dev/ieee1394/firewirereg.h:1.18
--- src/sys/dev/ieee1394/firewirereg.h:1.17	Sun Apr 29 18:31:40 2012
+++ src/sys/dev/ieee1394/firewirereg.h	Sat Aug  4 03:55:43 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: firewirereg.h,v 1.17 2012/04/29 18:31:40 dsl Exp $	*/
+/*	$NetBSD: firewirereg.h,v 1.18 2012/08/04 03:55:43 riastradh Exp $	*/
 /*-
  * Copyright (c) 2003 Hidetoshi Shimokawa
  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
@@ -283,6 +283,7 @@ int fw_xferwait(struct fw_xfer *);
 void fw_drain_txq(struct firewire_comm *);
 void fw_busreset(struct firewire_comm *, uint32_t);
 void fw_init(struct firewire_comm *);
+void fw_destroy(struct firewire_comm *);
 struct fw_bind *fw_bindlookup(struct firewire_comm *, uint16_t, uint32_t);
 int fw_bindadd(struct firewire_comm *, struct fw_bind *);
 int fw_bindremove(struct firewire_comm *, struct fw_bind *);

Index: src/sys/dev/ieee1394/fwohci.c
diff -u src/sys/dev/ieee1394/fwohci.c:1.132 src/sys/dev/ieee1394/fwohci.c:1.133
--- src/sys/dev/ieee1394/fwohci.c:1.132	Sun Jul 31 13:51:53 2011
+++ src/sys/dev/ieee1394/fwohci.c	Sat Aug  4 03:55:43 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: fwohci.c,v 1.132 2011/07/31 13:51:53 uebayasi Exp $	*/
+/*	$NetBSD: fwohci.c,v 1.133 2012/08/04 03:55:43 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2003 Hidetoshi Shimokawa
@@ -37,7 +37,7 @@
  *
  */
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.132 2011/07/31 13:51:53 uebayasi Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.133 2012/08/04 03:55:43 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -323,38 +323,15 @@ static void fwohci_arcv(struct fwohci_so
 #define IRX_CH	36
 
 
-int
+/*
+ * Call fwohci_init before fwohci_attach to initialize the kernel's
+ * data structures well enough that fwohci_detach won't crash, even if
+ * fwohci_attach fails.
+ */
+
+void
 fwohci_init(struct fwohci_softc *sc)
 {
-	uint32_t reg;
-	uint8_t ui[8];
-	int i, mver;
-
-/* OHCI version */
-	reg = OREAD(sc, OHCI_VERSION);
-	mver = (reg >> 16) & 0xff;
-	aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n",
-	    mver, reg & 0xff, (reg >> 24) & 1);
-	if (mver < 1 || mver > 9) {
-		aprint_error_dev(sc->fc.dev, "invalid OHCI version\n");
-		return ENXIO;
-	}
-
-/* Available Isochronous DMA channel probe */
-	OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
-	OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
-	reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
-	OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
-	OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
-	for (i = 0; i < 0x20; i++)
-		if ((reg & (1 << i)) == 0)
-			break;
-	sc->fc.nisodma = i;
-	aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n",
-	    i);
-	if (i == 0)
-		return ENXIO;
-
 	sc->fc.arq = &sc->arrq.xferq;
 	sc->fc.ars = &sc->arrs.xferq;
 	sc->fc.atq = &sc->atrq.xferq;
@@ -395,6 +372,68 @@ fwohci_init(struct fwohci_softc *sc)
 	sc->atrq.off = OHCI_ATQOFF;
 	sc->atrs.off = OHCI_ATSOFF;
 
+	sc->fc.tcode = tinfo;
+
+	sc->fc.cyctimer = fwohci_cyctimer;
+	sc->fc.ibr = fwohci_ibr;
+	sc->fc.set_bmr = fwohci_set_bus_manager;
+	sc->fc.ioctl = fwohci_ioctl;
+	sc->fc.irx_enable = fwohci_irx_enable;
+	sc->fc.irx_disable = fwohci_irx_disable;
+
+	sc->fc.itx_enable = fwohci_itxbuf_enable;
+	sc->fc.itx_disable = fwohci_itx_disable;
+	sc->fc.timeout = fwohci_timeout;
+	sc->fc.set_intr = fwohci_set_intr;
+#if BYTE_ORDER == BIG_ENDIAN
+	sc->fc.irx_post = fwohci_irx_post;
+#else
+	sc->fc.irx_post = NULL;
+#endif
+	sc->fc.itx_post = NULL;
+
+	sc->intmask = sc->irstat = sc->itstat = 0;
+
+	fw_init(&sc->fc);
+}
+
+/*
+ * Call fwohci_attach after fwohci_init to initialize the hardware and
+ * attach children.
+ */
+
+int
+fwohci_attach(struct fwohci_softc *sc)
+{
+	uint32_t reg;
+	uint8_t ui[8];
+	int i, mver;
+
+/* OHCI version */
+	reg = OREAD(sc, OHCI_VERSION);
+	mver = (reg >> 16) & 0xff;
+	aprint_normal_dev(sc->fc.dev, "OHCI version %x.%x (ROM=%d)\n",
+	    mver, reg & 0xff, (reg >> 24) & 1);
+	if (mver < 1 || mver > 9) {
+		aprint_error_dev(sc->fc.dev, "invalid OHCI version\n");
+		return ENXIO;
+	}
+
+/* Available Isochronous DMA channel probe */
+	OWRITE(sc, OHCI_IT_MASK, 0xffffffff);
+	OWRITE(sc, OHCI_IR_MASK, 0xffffffff);
+	reg = OREAD(sc, OHCI_IT_MASK) & OREAD(sc, OHCI_IR_MASK);
+	OWRITE(sc, OHCI_IT_MASKCLR, 0xffffffff);
+	OWRITE(sc, OHCI_IR_MASKCLR, 0xffffffff);
+	for (i = 0; i < 0x20; i++)
+		if ((reg & (1 << i)) == 0)
+			break;
+	sc->fc.nisodma = i;
+	aprint_normal_dev(sc->fc.dev, "No. of Isochronous channels is %d.\n",
+	    i);
+	if (i == 0)
+		return ENXIO;
+
 	for (i = 0; i < sc->fc.nisodma; i++) {
 		sc->fc.it[i] = &sc->it[i].xferq;
 		sc->fc.ir[i] = &sc->ir[i].xferq;
@@ -406,8 +445,6 @@ fwohci_init(struct fwohci_softc *sc)
 		sc->ir[i].off = OHCI_IROFF(i);
 	}
 
-	sc->fc.tcode = tinfo;
-
 	sc->fc.config_rom = fwdma_alloc_setup(sc->fc.dev, sc->fc.dmat,
 	    CROMSIZE, &sc->crom_dma, CROMSIZE, BUS_DMA_NOWAIT);
 	if (sc->fc.config_rom == NULL) {
@@ -467,27 +504,6 @@ fwohci_init(struct fwohci_softc *sc)
 	    "EUI64 %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
 	    ui[0], ui[1], ui[2], ui[3], ui[4], ui[5], ui[6], ui[7]);
 
-	sc->fc.cyctimer = fwohci_cyctimer;
-	sc->fc.ibr = fwohci_ibr;
-	sc->fc.set_bmr = fwohci_set_bus_manager;
-	sc->fc.ioctl = fwohci_ioctl;
-	sc->fc.irx_enable = fwohci_irx_enable;
-	sc->fc.irx_disable = fwohci_irx_disable;
-
-	sc->fc.itx_enable = fwohci_itxbuf_enable;
-	sc->fc.itx_disable = fwohci_itx_disable;
-	sc->fc.timeout = fwohci_timeout;
-	sc->fc.set_intr = fwohci_set_intr;
-#if BYTE_ORDER == BIG_ENDIAN
-	sc->fc.irx_post = fwohci_irx_post;
-#else
-	sc->fc.irx_post = NULL;
-#endif
-	sc->fc.itx_post = NULL;
-
-	sc->intmask = sc->irstat = sc->itstat = 0;
-
-	fw_init(&sc->fc);
 	fwohci_reset(sc);
 
 	sc->fc.bdev =
@@ -499,10 +515,13 @@ fwohci_init(struct fwohci_softc *sc)
 int
 fwohci_detach(struct fwohci_softc *sc, int flags)
 {
-	int i;
+	int i, rv;
 
-	if (sc->fc.bdev != NULL)
-		config_detach(sc->fc.bdev, flags);
+	if (sc->fc.bdev != NULL) {
+		rv = config_detach(sc->fc.bdev, flags);
+		if (rv)
+			return rv;
+	}
 	if (sc->sid_buf != NULL)
 		fwdma_free(sc->sid_dma.dma_tag, sc->sid_dma.dma_map,
 		    sc->sid_dma.v_addr);
@@ -519,10 +538,7 @@ fwohci_detach(struct fwohci_softc *sc, i
 		fwohci_db_free(sc, &sc->ir[i]);
 	}
 
-	mutex_destroy(&sc->arrq.xferq.q_mtx);
-	mutex_destroy(&sc->arrs.xferq.q_mtx);
-	mutex_destroy(&sc->atrq.xferq.q_mtx);
-	mutex_destroy(&sc->atrs.xferq.q_mtx);
+	fw_destroy(&sc->fc);
 
 	return 0;
 }

Index: src/sys/dev/ieee1394/fwohcivar.h
diff -u src/sys/dev/ieee1394/fwohcivar.h:1.33 src/sys/dev/ieee1394/fwohcivar.h:1.34
--- src/sys/dev/ieee1394/fwohcivar.h:1.33	Sun Apr 29 18:31:40 2012
+++ src/sys/dev/ieee1394/fwohcivar.h	Sat Aug  4 03:55:43 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: fwohcivar.h,v 1.33 2012/04/29 18:31:40 dsl Exp $	*/
+/*	$NetBSD: fwohcivar.h,v 1.34 2012/08/04 03:55:43 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2003 Hidetoshi SHimokawa
@@ -77,7 +77,8 @@ struct fwohci_softc {
 #define OWRITE(sc, r, x) bus_space_write_4((sc)->bst, (sc)->bsh, (r), (x))
 #define OREAD(sc, r)	bus_space_read_4((sc)->bst, (sc)->bsh, (r))
 
-int fwohci_init(struct fwohci_softc *);
+void fwohci_init(struct fwohci_softc *);
+int fwohci_attach(struct fwohci_softc *);
 int fwohci_detach(struct fwohci_softc *, int);
 int fwohci_intr(void *arg);
 int fwohci_resume(struct fwohci_softc *);

Index: src/sys/dev/pci/fwohci_pci.c
diff -u src/sys/dev/pci/fwohci_pci.c:1.40 src/sys/dev/pci/fwohci_pci.c:1.41
--- src/sys/dev/pci/fwohci_pci.c:1.40	Mon Jan 30 19:41:19 2012
+++ src/sys/dev/pci/fwohci_pci.c	Sat Aug  4 03:55:44 2012
@@ -1,4 +1,4 @@
-/*	$NetBSD: fwohci_pci.c,v 1.40 2012/01/30 19:41:19 drochner Exp $	*/
+/*	$NetBSD: fwohci_pci.c,v 1.41 2012/08/04 03:55:44 riastradh Exp $	*/
 
 /*-
  * Copyright (c) 2000 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.40 2012/01/30 19:41:19 drochner Exp $");
+__KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.41 2012/08/04 03:55:44 riastradh Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -102,6 +102,8 @@ fwohci_pci_attach(device_t parent, devic
 
 	pci_aprint_devinfo(pa, "IEEE 1394 Controller");
 
+	fwohci_init(&psc->psc_sc);
+
 	psc->psc_sc.fc.dev = self;
 	psc->psc_sc.fc.dmat = pa->pa_dmat;
 	psc->psc_pc = pa->pa_pc;
@@ -149,15 +151,12 @@ fwohci_pci_attach(device_t parent, devic
 	}
 	aprint_normal_dev(self, "interrupting at %s\n", intrstr);
 
+	if (fwohci_attach(&psc->psc_sc) != 0)
+		goto fail;
+
 	if (!pmf_device_register(self, fwohci_pci_suspend, fwohci_pci_resume))
 		aprint_error_dev(self, "couldn't establish power handler\n");
 
-	if (fwohci_init(&psc->psc_sc) != 0) {
-		pci_intr_disestablish(pa->pa_pc, psc->psc_ih);
-		bus_space_unmap(psc->psc_sc.bst, psc->psc_sc.bsh,
-		    psc->psc_sc.bssize);
-	}
-
 	return;
 
 fail:

Reply via email to