Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev Fix error branches and config pending races in firew...



details:   https://anonhg.NetBSD.org/src/rev/3c013772d511
branches:  trunk
changeset: 780699:3c013772d511
user:      riastradh <riastradh%NetBSD.org@localhost>
date:      Sat Aug 04 03:55:43 2012 +0000

description:
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).

diffstat:

 sys/dev/cardbus/fwohci_cardbus.c |    8 +-
 sys/dev/ieee1394/firewire.c      |   16 +++-
 sys/dev/ieee1394/firewirereg.h   |    3 +-
 sys/dev/ieee1394/fwohci.c        |  140 +++++++++++++++++++++-----------------
 sys/dev/ieee1394/fwohcivar.h     |    5 +-
 sys/dev/pci/fwohci_pci.c         |   15 +--
 6 files changed, 106 insertions(+), 81 deletions(-)

diffs (truncated from 368 to 300 lines):

diff -r 64c0c4e6270a -r 3c013772d511 sys/dev/cardbus/fwohci_cardbus.c
--- a/sys/dev/cardbus/fwohci_cardbus.c  Sat Aug 04 03:53:55 2012 +0000
+++ b/sys/dev/cardbus/fwohci_cardbus.c  Sat Aug 04 03:55:43 2012 +0000
@@ -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 @@
               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 @@
        }
 
        /* 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;
        }
diff -r 64c0c4e6270a -r 3c013772d511 sys/dev/ieee1394/firewire.c
--- a/sys/dev/ieee1394/firewire.c       Sat Aug 04 03:53:55 2012 +0000
+++ b/sys/dev/ieee1394/firewire.c       Sat Aug 04 03:55:43 2012 +0000
@@ -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 @@
        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 @@
        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 @@
 {
        struct firewire_comm *fc = (struct firewire_comm *)arg;
 
-       config_pending_decr();
-
        mutex_enter(&fc->wait_lock);
        while (fc->status != FWBUSDETACH) {
                if (fc->status == FWBUSEXPLORE) {
diff -r 64c0c4e6270a -r 3c013772d511 sys/dev/ieee1394/firewirereg.h
--- a/sys/dev/ieee1394/firewirereg.h    Sat Aug 04 03:53:55 2012 +0000
+++ b/sys/dev/ieee1394/firewirereg.h    Sat Aug 04 03:55:43 2012 +0000
@@ -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 @@
 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 *);
diff -r 64c0c4e6270a -r 3c013772d511 sys/dev/ieee1394/fwohci.c
--- a/sys/dev/ieee1394/fwohci.c Sat Aug 04 03:53:55 2012 +0000
+++ b/sys/dev/ieee1394/fwohci.c Sat Aug 04 03:55:43 2012 +0000
@@ -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 @@
 #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 @@
        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 @@
                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 @@
            "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 @@
 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_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);



Home | Main Index | Thread Index | Old Index