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).
This commit is contained in:
parent
3a4a1ac26a
commit
934b1cc688
@ -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, device_t self, void *aux)
|
||||
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, device_t self, void *aux)
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
@ -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 self, void *aux)
|
||||
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) {
|
||||
|
@ -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 *);
|
||||
|
@ -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_softc *, struct fwohci_dbch *);
|
||||
#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, int flags)
|
||||
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;
|
||||
}
|
||||
|
@ -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 *);
|
||||
|
@ -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, device_t self, void *aux)
|
||||
|
||||
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, device_t self, void *aux)
|
||||
}
|
||||
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:
|
||||
|
Loading…
Reference in New Issue
Block a user