==== //depot/projects/wifi/sys/dev/ath/ath_rate/sample/sample.c#12 - /opt/sam_wifi/sys/dev/ath/ath_rate/sample/sample.c ==== --- /tmp/tmp.593.86 2007-06-25 23:30:12.000000000 +0800 +++ /opt/sam_wifi/sys/dev/ath/ath_rate/sample/sample.c 2007-06-25 20:40:11.000000000 +0800 @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/ath_ #include #include #include -#include +#include #include #include ==== //depot/projects/wifi/sys/dev/ath/if_ath.c#146 - /opt/sam_wifi/sys/dev/ath/if_ath.c ==== --- /tmp/tmp.593.146 2007-06-25 23:30:15.000000000 +0800 +++ /opt/sam_wifi/sys/dev/ath/if_ath.c 2007-06-25 23:29:22.000000000 +0800 @@ -49,7 +49,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/if_a #include #include #include -#include +#include #include #include #include @@ -104,7 +104,6 @@ enum { static void ath_init(void *); static void ath_stop_locked(struct ifnet *); -static void ath_stop(struct ifnet *); static void ath_start(struct ifnet *); static int ath_reset(struct ifnet *); static int ath_media_change(struct ifnet *); @@ -656,7 +655,7 @@ bad: } int -ath_detach(struct ath_softc *sc) +ath_detach(struct ath_softc *sc, struct resource *irq, void *irq_handler) { struct ifnet *ifp = sc->sc_ifp; @@ -667,7 +666,12 @@ ath_detach(struct ath_softc *sc) if (ifp->if_capenable & IFCAP_POLLING) ether_poll_deregister(ifp); #endif - ath_stop(ifp); + ATH_LOCK(sc); + ath_stop_locked(ifp); + ATH_UNLOCK(sc); + + bus_teardown_intr(sc->sc_dev, irq, irq_handler); + bpfdetach(ifp); /* * NB: the order of these is important: @@ -676,6 +680,8 @@ ath_detach(struct ath_softc *sc) * key cache entries can be handled * o reclaim the tx queue data structures after calling * the 802.11 layer as we'll get called back to reclaim + * o and before powering down the chip since the hal may + * touch registers outside the PCI clock domain * node state and potentially want to use them * o to cleanup the tx queues the hal is called, so detach * it last @@ -687,10 +693,30 @@ ath_detach(struct ath_softc *sc) sc->sc_tx99->detach(sc->sc_tx99); #endif taskqueue_free(sc->sc_tq); +printf("%s: taskqueue_free done\n", __func__); ath_rate_detach(sc->sc_rc); ath_desc_free(sc); ath_tx_cleanup(sc); + if (!sc->sc_invalid) { + /* + * Set the chip in full sleep mode. Note that we are + * careful to do this only when bringing the interface + * completely to a stop. When the chip is in this state + * it must be carefully woken up or references to + * registers in the PCI clock domain may freeze the bus + * (and system). This varies by chip and is mostly an + * issue with newer parts that go to sleep more quickly. + */ +printf("%s: power down pre\n", __func__); + DELAY(5000); +printf("%s: power down begin\n", __func__); + ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); +printf("%s: power down end\n", __func__); + DELAY(5000); + } +printf("%s: hal detach begin\n", __func__); ath_hal_detach(sc->sc_ah); +printf("%s: hal detach end\n", __func__); if_free(ifp); return 0; @@ -704,25 +730,31 @@ ath_suspend(struct ath_softc *sc) DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", __func__, ifp->if_flags); - ath_stop(ifp); + ATH_LOCK(sc); + ath_stop_locked(ifp); + ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); + ATH_UNLOCK(sc); } void ath_resume(struct ath_softc *sc) { struct ifnet *ifp = sc->sc_ifp; + struct ath_hal *ah = sc->sc_ah; DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", __func__, ifp->if_flags); + ath_hal_setpower(ah, HAL_PM_AWAKE); + if (ifp->if_flags & IFF_UP) { ath_init(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) ath_start(ifp); } if (sc->sc_softled) { - ath_hal_gpioCfgOutput(sc->sc_ah, sc->sc_ledpin); - ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon); + ath_hal_gpioCfgOutput(ah, sc->sc_ledpin); + ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon); } } @@ -734,7 +766,11 @@ ath_shutdown(struct ath_softc *sc) DPRINTF(sc, ATH_DEBUG_ANY, "%s: if_flags %x\n", __func__, ifp->if_flags); - ath_stop(ifp); + ATH_LOCK(sc); + ath_stop_locked(ifp); + if (!sc->sc_invalid) + ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); + ATH_UNLOCK(sc); } /* @@ -854,6 +890,10 @@ ath_intr(void *arg) struct ifnet *ifp = sc->sc_ifp; struct ath_hal *ah = sc->sc_ah; +#if 0 +printf("%s enter\n", __func__); +#endif + if (ifp->if_capenable & IFCAP_POLLING) return; if (sc->sc_invalid) { @@ -1155,28 +1195,6 @@ ath_stop_locked(struct ifnet *ifp) } } -static void -ath_stop(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - - ATH_LOCK(sc); - ath_stop_locked(ifp); - if (!sc->sc_invalid) { - /* - * Set the chip in full sleep mode. Note that we are - * careful to do this only when bringing the interface - * completely to a stop. When the chip is in this state - * it must be carefully woken up or references to - * registers in the PCI clock domain may freeze the bus - * (and system). This varies by chip and is mostly an - * issue with newer parts that go to sleep more quickly. - */ - ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); - } - ATH_UNLOCK(sc); -} - /* * Reset the hardware w/o losing operational state. This is * basically a more efficient way of doing ath_stop, ath_init, @@ -5179,6 +5197,10 @@ ath_calibrate(void *arg) struct ath_hal *ah = sc->sc_ah; HAL_BOOL iqCalDone; +#if 0 +printf("%s enter\n", __func__); +#endif + sc->sc_stats.ast_per_cal++; if (ath_hal_getrfgain(ah) == HAL_RFGAIN_NEED_CHANGE) { @@ -5225,6 +5247,10 @@ ath_calibrate(void *arg) sc->sc_caltries++; callout_reset(&sc->sc_cal_ch, sc->sc_calinterval * hz, ath_calibrate, sc); + +#if 0 +printf("%s leave\n", __func__); +#endif } static void @@ -5318,13 +5344,11 @@ ath_newstate(struct ieee80211com *ic, en */ sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS); ath_intrset(sc, sc->sc_imask &~ HAL_INT_GLOBAL); -#if 0 - /* XXX can't use taskqueue_drain 'cuz we're holding sc_mtx */ taskqueue_drain(sc->sc_tq, &sc->sc_rxtask); + taskqueue_drain(sc->sc_tq, &sc->sc_txtask); taskqueue_drain(sc->sc_tq, &sc->sc_rxorntask); taskqueue_drain(sc->sc_tq, &sc->sc_bmisstask); taskqueue_drain(sc->sc_tq, &sc->sc_bstucktask); -#endif ath_rate_newstate(sc, nstate); goto done; } @@ -5591,8 +5615,10 @@ ath_led_off(void *arg) { struct ath_softc *sc = arg; +printf("%s enter\n", __func__); ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, !sc->sc_ledon); callout_reset(&sc->sc_ledtimer, sc->sc_ledoff, ath_led_done, sc); +printf("%s leave\n", __func__); } /* @@ -5602,10 +5628,13 @@ static void ath_led_blink(struct ath_softc *sc, int on, int off) { DPRINTF(sc, ATH_DEBUG_LED, "%s: on %u off %u\n", __func__, on, off); + +printf("%s enter\n", __func__); ath_hal_gpioset(sc->sc_ah, sc->sc_ledpin, sc->sc_ledon); sc->sc_blinking = 1; sc->sc_ledoff = off; callout_reset(&sc->sc_ledtimer, on, ath_led_off, sc); +printf("%s leave\n", __func__); } static void ==== //depot/projects/wifi/sys/dev/ath/if_ath_pci.c#14 - /opt/sam_wifi/sys/dev/ath/if_ath_pci.c ==== --- /tmp/tmp.593.194 2007-06-25 23:30:16.000000000 +0800 +++ /opt/sam_wifi/sys/dev/ath/if_ath_pci.c 2007-06-25 22:11:53.000000000 +0800 @@ -39,7 +39,7 @@ __FBSDID("$FreeBSD: src/sys/dev/ath/if_a #include #include #include -#include +#include #include #include @@ -213,10 +213,9 @@ ath_pci_detach(device_t dev) /* check if device was removed */ sc->sc_invalid = !bus_child_present(dev); - ath_detach(sc); + ath_detach(sc, psc->sc_irq, psc->sc_ih); bus_generic_detach(dev); - bus_teardown_intr(dev, psc->sc_irq, psc->sc_ih); bus_release_resource(dev, SYS_RES_IRQ, 0, psc->sc_irq); bus_dma_tag_destroy(sc->sc_dmat); ==== //depot/projects/wifi/sys/dev/ath/if_athvar.h#58 - /opt/sam_wifi/sys/dev/ath/if_athvar.h ==== --- /tmp/tmp.593.258 2007-06-25 23:30:16.000000000 +0800 +++ /opt/sam_wifi/sys/dev/ath/if_athvar.h 2007-06-25 22:11:27.000000000 +0800 @@ -197,7 +197,7 @@ struct ath_softc { HAL_BUS_TAG sc_st; /* bus space tag */ HAL_BUS_HANDLE sc_sh; /* bus space handle */ bus_dma_tag_t sc_dmat; /* bus DMA tag */ - struct mtx sc_mtx; /* master lock (recursive) */ + struct sx sc_mtx; /* master lock (recursive) */ struct taskqueue *sc_tq; /* private task queue */ struct ath_hal *sc_ah; /* Atheros HAL */ struct ath_ratectrl *sc_rc; /* tx rate control support */ @@ -321,12 +321,12 @@ struct ath_softc { #define sc_rx_th u_rx_rt.th #define ATH_LOCK_INIT(_sc) \ - mtx_init(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ - NULL, MTX_DEF | MTX_RECURSE) -#define ATH_LOCK_DESTROY(_sc) mtx_destroy(&(_sc)->sc_mtx) -#define ATH_LOCK(_sc) mtx_lock(&(_sc)->sc_mtx) -#define ATH_UNLOCK(_sc) mtx_unlock(&(_sc)->sc_mtx) -#define ATH_LOCK_ASSERT(_sc) mtx_assert(&(_sc)->sc_mtx, MA_OWNED) + sx_init_flags(&(_sc)->sc_mtx, device_get_nameunit((_sc)->sc_dev), \ + SX_RECURSE) +#define ATH_LOCK_DESTROY(_sc) sx_destroy(&(_sc)->sc_mtx) +#define ATH_LOCK(_sc) sx_xlock(&(_sc)->sc_mtx) +#define ATH_UNLOCK(_sc) sx_xunlock(&(_sc)->sc_mtx) +#define ATH_LOCK_ASSERT(_sc) sx_assert(&(_sc)->sc_mtx, SA_LOCKED) #define ATH_TXQ_SETUP(sc, i) ((sc)->sc_txqsetup & (1<sc_txbuflock, MA_OWNED) int ath_attach(u_int16_t, struct ath_softc *); -int ath_detach(struct ath_softc *); +int ath_detach(struct ath_softc *, struct resource *, void *); void ath_resume(struct ath_softc *); void ath_suspend(struct ath_softc *); void ath_shutdown(struct ath_softc *);