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: