Date: Sun, 17 Sep 2000 09:44:10 -0400 From: mike ryan <msr@elision.org> To: David Greenman <dg@root.com> Cc: freebsd-current@FreeBSD.ORG Subject: Re: fxp suspend/resume hangs Message-ID: <20000917094410.A57878@medianstrip.net> In-Reply-To: <200009171315.GAA26649@implode.root.com>; from dg@root.com on Sun, Sep 17, 2000 at 06:15:45AM -0700 References: <20000917002733.A37043@medianstrip.net> <200009171315.GAA26649@implode.root.com>
next in thread | previous in thread | raw e-mail | index | archive | help
On Sun, Sep 17, 2000 at 06:15:45AM -0700, David Greenman wrote: > I've made a few changes to the patches which should address my primary > concerns. Instead of using IFF_RUNNING, I added a new softc variable to > track the suspended condition. Only the APM stuff should call suspend/resume, > so the interrupt logic should be uneffected in non-APM machines. Please try > these patches out and let me know if they work as expected. They should apply > and work with both -stable and -current. yup, suspend/resume still works fine with this new patch. thanks, and sorry i've been such a pest about this... > -DG > > David Greenman > Co-founder, The FreeBSD Project - http://www.freebsd.org > President, TeraSolutions, Inc. - http://www.terasolutions.com > Pave the road of life with opportunities. > > Index: if_fxp.c > =================================================================== > RCS file: /home/ncvs/src/sys/pci/if_fxp.c,v > retrieving revision 1.77.2.3 > diff -c -r1.77.2.3 if_fxp.c > *** if_fxp.c 2000/06/19 00:54:30 1.77.2.3 > --- if_fxp.c 2000/09/17 13:15:33 > *************** > *** 125,135 **** > --- 125,139 ---- > fxp_lwcopy(src, dst) > volatile u_int32_t *src, *dst; > { > + #ifdef __i386__ > + *dst = *src; > + #else > volatile u_int16_t *a = (volatile u_int16_t *)src; > volatile u_int16_t *b = (volatile u_int16_t *)dst; > > b[0] = a[0]; > b[1] = a[1]; > + #endif > } > > /* > *************** > *** 215,220 **** > --- 219,225 ---- > static void fxp_mediastatus __P((struct ifnet *, struct ifmediareq *)); > static void fxp_set_media __P((struct fxp_softc *, int)); > static __inline void fxp_scb_wait __P((struct fxp_softc *)); > + static __inline void fxp_dma_wait __P((volatile u_int16_t *, struct fxp_softc *sc)); > static FXP_INTR_TYPE fxp_intr __P((void *)); > static void fxp_start __P((struct ifnet *)); > static int fxp_ioctl __P((struct ifnet *, > *************** > *** 283,290 **** > struct fxp_softc *sc; > { > int i = 10000; > > ! while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i); > } > > /************************************************************* > --- 288,311 ---- > struct fxp_softc *sc; > { > int i = 10000; > + > + while (CSR_READ_1(sc, FXP_CSR_SCB_COMMAND) && --i) > + DELAY(2); > + if (i == 0) > + printf(FXP_FORMAT ": SCB timeout\n", FXP_ARGS(sc)); > + } > + > + static __inline void > + fxp_dma_wait(status, sc) > + volatile u_int16_t *status; > + struct fxp_softc *sc; > + { > + int i = 10000; > > ! while (!(*status & FXP_CB_STATUS_C) && --i) > ! DELAY(2); > ! if (i == 0) > ! printf(FXP_FORMAT ": DMA timeout\n", FXP_ARGS(sc)); > } > > /************************************************************* > *************** > *** 679,690 **** > --- 700,784 ---- > return 0; > } > > + /* > + * Device suspend routine. Stop the interface and save some PCI > + * settings in case the BIOS doesn't restore them properly on > + * resume. > + */ > + static int > + fxp_suspend(device_t dev) > + { > + struct fxp_softc *sc = device_get_softc(dev); > + int i, s; > + > + s = splimp(); > + > + fxp_stop(sc); > + > + for (i=0; i<5; i++) > + sc->saved_maps[i] = pci_read_config(dev, PCIR_MAPS + i*4, 4); > + sc->saved_biosaddr = pci_read_config(dev, PCIR_BIOS, 4); > + sc->saved_intline = pci_read_config(dev, PCIR_INTLINE, 1); > + sc->saved_cachelnsz = pci_read_config(dev, PCIR_CACHELNSZ, 1); > + sc->saved_lattimer = pci_read_config(dev, PCIR_LATTIMER, 1); > + > + sc->suspended = 1; > + > + splx(s); > + > + return 0; > + } > + > + /* > + * Device resume routine. Restore some PCI settings in case the BIOS > + * doesn't, re-enable busmastering, and restart the interface if > + * appropriate. > + */ > + static int > + fxp_resume(device_t dev) > + { > + struct fxp_softc *sc = device_get_softc(dev); > + struct ifnet *ifp = &sc->sc_if; > + u_int16_t pci_command; > + int i, s; > + > + s = splimp(); > + > + /* better way to do this? */ > + for (i=0; i<5; i++) > + pci_write_config(dev, PCIR_MAPS + i*4, sc->saved_maps[i], 4); > + pci_write_config(dev, PCIR_BIOS, sc->saved_biosaddr, 4); > + pci_write_config(dev, PCIR_INTLINE, sc->saved_intline, 1); > + pci_write_config(dev, PCIR_CACHELNSZ, sc->saved_cachelnsz, 1); > + pci_write_config(dev, PCIR_LATTIMER, sc->saved_lattimer, 1); > + > + /* reenable busmastering */ > + pci_command = pci_read_config(dev, PCIR_COMMAND, 2); > + pci_command |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); > + pci_write_config(dev, PCIR_COMMAND, pci_command, 2); > + > + CSR_WRITE_4(sc, FXP_CSR_PORT, FXP_PORT_SELECTIVE_RESET); > + DELAY(10); > + > + /* reinitialize interface if necessary */ > + if (ifp->if_flags & IFF_UP) > + fxp_init(sc); > + > + sc->suspended = 0; > + > + splx(s); > + > + return 0; > + } > + > static device_method_t fxp_methods[] = { > /* Device interface */ > DEVMETHOD(device_probe, fxp_probe), > DEVMETHOD(device_attach, fxp_attach), > DEVMETHOD(device_detach, fxp_detach), > DEVMETHOD(device_shutdown, fxp_shutdown), > + DEVMETHOD(device_suspend, fxp_suspend), > + DEVMETHOD(device_resume, fxp_resume), > > { 0, 0 } > }; > *************** > *** 1095,1101 **** > int claimed = 0; > #endif > > ! while ((statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) { > #if defined(__NetBSD__) > claimed = 1; > #endif > --- 1189,1195 ---- > int claimed = 0; > #endif > > ! while (!sc->suspended && (statack = CSR_READ_1(sc, FXP_CSR_SCB_STATACK)) != 0) { > #if defined(__NetBSD__) > claimed = 1; > #endif > *************** > *** 1158,1164 **** > */ > if (fxp_add_rfabuf(sc, m) == 0) { > struct ether_header *eh; > ! u_int16_t total_len; > > total_len = rfa->actual_size & > (MCLBYTES - 1); > --- 1252,1258 ---- > */ > if (fxp_add_rfabuf(sc, m) == 0) { > struct ether_header *eh; > ! int total_len; > > total_len = rfa->actual_size & > (MCLBYTES - 1); > *************** > *** 1317,1322 **** > --- 1411,1419 ---- > struct fxp_cb_tx *txp; > int i; > > + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); > + ifp->if_timer = 0; > + > /* > * Cancel stats updater. > */ > *************** > *** 1359,1367 **** > panic("fxp_stop: no buffers!"); > } > } > - > - ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); > - ifp->if_timer = 0; > } > > /* > --- 1456,1461 ---- > *************** > *** 1474,1480 **** > CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status)); > CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); > /* ...and wait for it to complete. */ > ! while (!(cbp->cb_status & FXP_CB_STATUS_C)); > > /* > * Now initialize the station address. Temporarily use the TxCB > --- 1568,1574 ---- > CSR_WRITE_4(sc, FXP_CSR_SCB_GENERAL, vtophys(&cbp->cb_status)); > CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); > /* ...and wait for it to complete. */ > ! fxp_dma_wait(&cbp->cb_status, sc); > > /* > * Now initialize the station address. Temporarily use the TxCB > *************** > *** 1497,1503 **** > fxp_scb_wait(sc); > CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); > /* ...and wait for it to complete. */ > ! while (!(cb_ias->cb_status & FXP_CB_STATUS_C)); > > /* > * Initialize transmit control block (TxCB) list. > --- 1591,1597 ---- > fxp_scb_wait(sc); > CSR_WRITE_1(sc, FXP_CSR_SCB_COMMAND, FXP_SCB_COMMAND_CU_START); > /* ...and wait for it to complete. */ > ! fxp_dma_wait(&cb_ias->cb_status, sc); > > /* > * Initialize transmit control block (TxCB) list. > *************** > *** 1936,1941 **** > --- 2030,2036 ---- > struct ifnet *ifp = &sc->sc_if; > struct ifmultiaddr *ifma; > int nmcasts; > + int count; > > /* > * If there are queued commands, we must wait until they are all > *************** > *** 2017,2024 **** > * Wait until command unit is not active. This should never > * be the case when nothing is queued, but make sure anyway. > */ > while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) == > ! FXP_SCB_CUS_ACTIVE) ; > > /* > * Start the multicast setup command. > --- 2112,2125 ---- > * Wait until command unit is not active. This should never > * be the case when nothing is queued, but make sure anyway. > */ > + count = 100; > while ((CSR_READ_1(sc, FXP_CSR_SCB_RUSCUS) >> 6) == > ! FXP_SCB_CUS_ACTIVE && --count) > ! DELAY(10); > ! if (count == 0) { > ! printf(FXP_FORMAT ": command queue timeout\n", FXP_ARGS(sc)); > ! return; > ! } > > /* > * Start the multicast setup command. > Index: if_fxpvar.h > =================================================================== > RCS file: /home/ncvs/src/sys/pci/if_fxpvar.h,v > retrieving revision 1.9.2.1 > diff -c -r1.9.2.1 if_fxpvar.h > *** if_fxpvar.h 2000/03/29 02:02:39 1.9.2.1 > --- if_fxpvar.h 2000/09/17 13:15:33 > *************** > *** 68,73 **** > --- 68,79 ---- > int phy_primary_device; /* device type of primary PHY */ > int phy_10Mbps_only; /* PHY is 10Mbps-only device */ > int eeprom_size; /* size of serial EEPROM */ > + int suspended; /* 0 = normal 1 = suspended (APM) */ > + u_int32_t saved_maps[5]; /* pci data */ > + u_int32_t saved_biosaddr; > + u_int8_t saved_intline; > + u_int8_t saved_cachelnsz; > + u_int8_t saved_lattimer; > }; > > /* Macros to ease CSR access. */ > To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20000917094410.A57878>