From 065a386bdcc4180b948790e8ec4df6b9dd574e4d Mon Sep 17 00:00:00 2001 From: simokawa Date: Sat, 28 Jun 2003 11:11:36 +0000 Subject: Fix several problems related to resume: - Initialize fc->status to process bus reset correctly after resume. - Initialize AT ring buffer pointer. - Requeue stdma to stfree for active IR buffer. - Stop DMA before suspend for safe. - Set powerstate after resume. --- sys/dev/firewire/firewire.c | 18 ++++++++++++++++-- sys/dev/firewire/firewirereg.h | 1 + sys/dev/firewire/fwohci.c | 22 ++++++++++++++++++++-- sys/dev/firewire/fwohci_pci.c | 4 +++- 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/sys/dev/firewire/firewire.c b/sys/dev/firewire/firewire.c index 3b100c2..25230ed 100644 --- a/sys/dev/firewire/firewire.c +++ b/sys/dev/firewire/firewire.c @@ -84,6 +84,7 @@ devclass_t firewire_devclass; static int firewire_match __P((device_t)); static int firewire_attach __P((device_t)); static int firewire_detach __P((device_t)); +static int firewire_resume __P((device_t)); #if 0 static int firewire_shutdown __P((device_t)); #endif @@ -109,7 +110,7 @@ static device_method_t firewire_methods[] = { DEVMETHOD(device_attach, firewire_attach), DEVMETHOD(device_detach, firewire_detach), DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), + DEVMETHOD(device_resume, firewire_resume), DEVMETHOD(device_shutdown, bus_generic_shutdown), /* Bus interface */ @@ -367,7 +368,7 @@ firewire_attach( device_t dev ) fc = (struct firewire_comm *)device_get_softc(pa); sc->fc = fc; - fc->status = -1; + fc->status = FWBUSNOTREADY; unitmask = UNIT2MIN(device_get_unit(dev)); @@ -434,6 +435,19 @@ firewire_add_child(device_t dev, int order, const char *name, int unit) return child; } +static int +firewire_resume(device_t dev) +{ + struct firewire_softc *sc; + + sc = (struct firewire_softc *)device_get_softc(dev); + sc->fc->status = FWBUSNOTREADY; + + bus_generic_resume(dev); + + return(0); +} + /* * Dettach it. */ diff --git a/sys/dev/firewire/firewirereg.h b/sys/dev/firewire/firewirereg.h index f16fd32..6a462c2 100644 --- a/sys/dev/firewire/firewirereg.h +++ b/sys/dev/firewire/firewirereg.h @@ -121,6 +121,7 @@ struct firewire_comm{ SLIST_HEAD(, csrdir) ongocsr; SLIST_HEAD(, csrdir) csrfree; u_int32_t status; +#define FWBUSNOTREADY (-1) #define FWBUSRESET 0 #define FWBUSINIT 1 #define FWBUSCYMELECT 2 diff --git a/sys/dev/firewire/fwohci.c b/sys/dev/firewire/fwohci.c index a597a34..4dfe5cf 100644 --- a/sys/dev/firewire/fwohci.c +++ b/sys/dev/firewire/fwohci.c @@ -549,10 +549,17 @@ fwohci_reset(struct fwohci_softc *sc, device_t dev) /* Initialize async TX */ OWRITE(sc, OHCI_ATQCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); OWRITE(sc, OHCI_ATSCTLCLR, OHCI_CNTL_DMA_RUN | OHCI_CNTL_DMA_DEAD); + /* AT Retries */ OWRITE(sc, FWOHCI_RETRY, /* CycleLimit PhyRespRetries ATRespRetries ATReqRetries */ (0xffff << 16 ) | (0x0f << 8) | (0x0f << 4) | 0x0f) ; + + sc->atrq.top = STAILQ_FIRST(&sc->atrq.db_trq); + sc->atrs.top = STAILQ_FIRST(&sc->atrs.db_trq); + sc->atrq.bottom = sc->atrq.top; + sc->atrs.bottom = sc->atrs.top; + for( i = 0, db_tr = sc->atrq.top; i < sc->atrq.ndb ; i ++, db_tr = STAILQ_NEXT(db_tr, link)){ db_tr->xfer = NULL; @@ -1681,6 +1688,9 @@ fwohci_stop(struct fwohci_softc *sc, device_t dev) | OHCI_INT_DMA_PRRQ | OHCI_INT_DMA_PRRS | OHCI_INT_DMA_ARRQ | OHCI_INT_DMA_ARRS | OHCI_INT_PHY_BUS_R); + + fw_drain_txq(&sc->fc); + /* XXX Link down? Bus reset? */ return 0; } @@ -1689,14 +1699,22 @@ int fwohci_resume(struct fwohci_softc *sc, device_t dev) { int i; + struct fw_xferq *ir; + struct fw_bulkxfer *chunk; fwohci_reset(sc, dev); /* XXX resume isochronus receive automatically. (how about TX?) */ for(i = 0; i < sc->fc.nisodma; i ++) { - if((sc->ir[i].xferq.flag & FWXFERQ_RUNNING) != 0) { + ir = &sc->ir[i].xferq; + if((ir->flag & FWXFERQ_RUNNING) != 0) { device_printf(sc->fc.dev, "resume iso receive ch: %d\n", i); - sc->ir[i].xferq.flag &= ~FWXFERQ_RUNNING; + ir->flag &= ~FWXFERQ_RUNNING; + /* requeue stdma to stfree */ + while((chunk = STAILQ_FIRST(&ir->stdma)) != NULL) { + STAILQ_REMOVE_HEAD(&ir->stdma, link); + STAILQ_INSERT_TAIL(&ir->stfree, chunk, link); + } sc->fc.irx_enable(&sc->fc, i); } } diff --git a/sys/dev/firewire/fwohci_pci.c b/sys/dev/firewire/fwohci_pci.c index 6f45152..dcc5caa 100644 --- a/sys/dev/firewire/fwohci_pci.c +++ b/sys/dev/firewire/fwohci_pci.c @@ -380,13 +380,14 @@ fwohci_pci_detach(device_t self) static int fwohci_pci_suspend(device_t dev) { + fwohci_softc_t *sc = device_get_softc(dev); int err; device_printf(dev, "fwohci_pci_suspend\n"); err = bus_generic_suspend(dev); if (err) return err; - /* fwohci_stop(dev); */ + fwohci_stop(sc, dev); return 0; } @@ -397,6 +398,7 @@ fwohci_pci_resume(device_t dev) device_printf(dev, "fwohci_pci_resume: power_state = 0x%08x\n", pci_get_powerstate(dev)); + pci_set_powerstate(dev, PCI_POWERSTATE_D0); fwohci_pci_init(dev); fwohci_resume(sc, dev); return 0; -- cgit v1.1