Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300.h @@ -1390,7 +1390,7 @@ extern HAL_BOOL ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing, - HAL_BOOL b_channel_change, HAL_STATUS *status, int is_scan); + HAL_BOOL b_channel_change, HAL_STATUS *status, HAL_RESET_TYPE reset_type, int is_scan); extern HAL_BOOL ar9300_lean_channel_change(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask); extern HAL_BOOL ar9300_set_reset_reg(struct ath_hal *ah, u_int32_t type); @@ -1400,7 +1400,7 @@ extern void ar9300_set_operating_mode(struct ath_hal *ah, int opmode); extern HAL_BOOL ar9300_phy_disable(struct ath_hal *ah); extern HAL_BOOL ar9300_disable(struct ath_hal *ah); -extern HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *); +extern HAL_BOOL ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *, HAL_RESET_TYPE type); extern HAL_BOOL ar9300_calibration(struct ath_hal *ah, struct ieee80211_channel *chan, u_int8_t rxchainmask, HAL_BOOL longcal, HAL_BOOL *isIQdone, int is_scan, u_int32_t *sched_cals); extern void ar9300_reset_cal_valid(struct ath_hal *ah, Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c @@ -543,6 +543,7 @@ HAL_HT_EXTPROTSPACING_20, /* always 20Mhz channel spacing */ bChannelChange, status, + resetType, AH_FALSE); /* XXX should really extend ath_hal_reset() */ return (r); Index: head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c =================================================================== --- head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c +++ head/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c @@ -2064,7 +2064,7 @@ * Places the hardware into reset and then pulls it out of reset */ HAL_BOOL -ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan) +ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan, HAL_RESET_TYPE reset_type) { struct ath_hal_9300 *ahp = AH9300(ah); int type = HAL_RESET_WARM; @@ -2080,8 +2080,13 @@ */ if (ahp->ah_chip_full_sleep || (ah->ah_config.ah_force_full_reset == 1) || + (reset_type == HAL_RESET_FORCE_COLD) || + (reset_type == HAL_RESET_BBPANIC) || OS_REG_READ(ah, AR_Q_TXE) || (OS_REG_READ(ah, AR_CR) & AR_CR_RXE)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: full reset; reset_type=%d, full_sleep=%d\n", + __func__, reset_type, ahp->ah_chip_full_sleep); type = HAL_RESET_COLD; } @@ -4510,7 +4515,7 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *chan, HAL_HT_MACMODE macmode, u_int8_t txchainmask, u_int8_t rxchainmask, HAL_HT_EXTPROTSPACING extprotspacing, HAL_BOOL b_channel_change, - HAL_STATUS *status, int is_scan) + HAL_STATUS *status, HAL_RESET_TYPE reset_type, int is_scan) { #define FAIL(_code) do { ecode = _code; goto bad; } while (0) u_int32_t save_led_state; @@ -4864,7 +4869,7 @@ /* Mark PHY inactive prior to reset, to be undone in ar9300_init_bb () */ ar9300_mark_phy_inactive(ah); - if (!ar9300_chip_reset(ah, chan)) { + if (!ar9300_chip_reset(ah, chan, reset_type)) { HALDEBUG(ah, HAL_DEBUG_RESET, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } Index: head/sys/dev/ath/ath_hal/ar5416/ar5416.h =================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416.h +++ head/sys/dev/ath/ath_hal/ar5416/ar5416.h @@ -306,7 +306,8 @@ extern HAL_RFGAIN ar5416GetRfgain(struct ath_hal *ah); extern HAL_BOOL ar5416Disable(struct ath_hal *ah); extern HAL_BOOL ar5416ChipReset(struct ath_hal *ah, - const struct ieee80211_channel *); + const struct ieee80211_channel *, + HAL_RESET_TYPE); extern int ar5416GetRegChainOffset(struct ath_hal *ah, int i); extern HAL_BOOL ar5416SetBoardValues(struct ath_hal *, const struct ieee80211_channel *); Index: head/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c =================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_attach.c @@ -376,7 +376,7 @@ if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; Index: head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c =================================================================== --- head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c +++ head/sys/dev/ath/ath_hal/ar5416/ar5416_reset.c @@ -170,13 +170,15 @@ if (AR_SREV_HOWL(ah) || (AR_SREV_MERLIN(ah) && ath_hal_eepromGetFlag(ah, AR_EEP_OL_PWRCTRL)) || + (resetType == HAL_RESET_FORCE_COLD) || + (resetType == HAL_RESET_BBPANIC) || (ah->ah_config.ah_force_full_reset)) tsf = ar5416GetTsf64(ah); /* Mark PHY as inactive; marked active in ar5416InitBB() */ ar5416MarkPhyInactive(ah); - if (!ar5416ChipReset(ah, chan)) { + if (!ar5416ChipReset(ah, chan, resetType)) { HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); FAIL(HAL_EIO); } @@ -775,7 +777,8 @@ * Places the hardware into reset and then pulls it out of reset */ HAL_BOOL -ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan) +ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan, + HAL_RESET_TYPE resetType) { OS_MARK(ah, AH_MARK_CHIPRESET, chan ? chan->ic_freq : 0); /* @@ -786,6 +789,13 @@ if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) return AH_FALSE; } else if (ah->ah_config.ah_force_full_reset) { + if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) + return AH_FALSE; + } else if ((resetType == HAL_RESET_FORCE_COLD) || + (resetType == HAL_RESET_BBPANIC)) { + HALDEBUG(ah, HAL_DEBUG_RESET, + "%s: full reset; resetType=%d\n", + __func__, resetType); if (!ar5416SetResetReg(ah, HAL_RESET_POWER_ON)) return AH_FALSE; } else { Index: head/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c =================================================================== --- head/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c +++ head/sys/dev/ath/ath_hal/ar9001/ar9130_attach.c @@ -173,7 +173,7 @@ if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; Index: head/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c =================================================================== --- head/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c +++ head/sys/dev/ath/ath_hal/ar9001/ar9160_attach.c @@ -200,7 +200,7 @@ HAL_INI_INIT(&AH5416(ah)->ah_ini_pcieserdes, ar9160PciePhy, 2); ar5416AttachPCIE(ah); - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; Index: head/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c =================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c +++ head/sys/dev/ath/ath_hal/ar9002/ar9280_attach.c @@ -259,7 +259,7 @@ if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; Index: head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c =================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c +++ head/sys/dev/ath/ath_hal/ar9002/ar9285_attach.c @@ -249,7 +249,7 @@ if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; Index: head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c =================================================================== --- head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c +++ head/sys/dev/ath/ath_hal/ar9002/ar9287_attach.c @@ -242,7 +242,7 @@ if (ecode != HAL_OK) goto bad; - if (!ar5416ChipReset(ah, AH_NULL)) { /* reset chip */ + if (!ar5416ChipReset(ah, AH_NULL, HAL_RESET_NORMAL)) { /* reset chip */ HALDEBUG(ah, HAL_DEBUG_ANY, "%s: chip reset failed\n", __func__); ecode = HAL_EIO; goto bad; Index: head/sys/dev/ath/if_ath.c =================================================================== --- head/sys/dev/ath/if_ath.c +++ head/sys/dev/ath/if_ath.c @@ -2380,7 +2380,7 @@ "0x%08x 0x%08x 0x%08x, 0x%08x 0x%08x 0x%08x\n", state[0], state[1] , state[2], state[3], state[4], state[5]); } - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); } static void @@ -2491,11 +2491,11 @@ * to clear. */ if (ath_hal_gethangstate(sc->sc_ah, 0xff, &hangs) && hangs != 0) { - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_BBPANIC); device_printf(sc->sc_dev, "bb hang detected (0x%x), resetting\n", hangs); } else { - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); ieee80211_beacon_miss(&sc->sc_ic); } @@ -2894,7 +2894,8 @@ * to reset or reload hardware state. */ int -ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type) +ath_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type, + HAL_RESET_TYPE ah_reset_type) { struct ieee80211com *ic = &sc->sc_ic; struct ath_hal *ah = sc->sc_ah; @@ -2962,7 +2963,7 @@ ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); if (!ath_hal_reset(ah, sc->sc_opmode, ic->ic_curchan, AH_TRUE, - HAL_RESET_NORMAL, &status)) + ah_reset_type, &status)) device_printf(sc->sc_dev, "%s: unable to reset hardware; hal status %u\n", __func__, status); @@ -3098,7 +3099,7 @@ return 0; } /* XXX? Full or NOLOSS? */ - return ath_reset(sc, ATH_RESET_FULL); + return ath_reset(sc, ATH_RESET_FULL, HAL_RESET_NORMAL); } struct ath_buf * @@ -3778,7 +3779,7 @@ #if 0 device_printf(sc->sc_dev, "%s: resetting\n", __func__); #endif - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); } /* @@ -3805,7 +3806,7 @@ * This assumes that there's no simultaneous channel mode change * occurring. */ - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_FORCE_COLD); } static int @@ -5460,6 +5461,10 @@ * infinite NIC restart. Ideally we'd not restart if we * failed the first NF cal - that /can/ fail sometimes in * a noisy environment. + * + * Instead, we should likely temporarily shorten the longCal + * period to happen pretty quickly and if a subsequent one + * fails, do a full reset. */ if (shortCal) sc->sc_lastshortcal = ticks; Index: head/sys/dev/ath/if_ath_misc.h =================================================================== --- head/sys/dev/ath/if_ath_misc.h +++ head/sys/dev/ath/if_ath_misc.h @@ -58,7 +58,8 @@ extern void ath_returnbuf_head(struct ath_softc *sc, struct ath_buf *bf); extern void ath_returnbuf_tail(struct ath_softc *sc, struct ath_buf *bf); -extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE); +extern int ath_reset(struct ath_softc *, ATH_RESET_TYPE, + HAL_RESET_TYPE ah_reset_type); extern void ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail); extern void ath_tx_update_ratectrl(struct ath_softc *sc, Index: head/sys/dev/ath/if_ath_sysctl.c =================================================================== --- head/sys/dev/ath/if_ath_sysctl.c +++ head/sys/dev/ath/if_ath_sysctl.c @@ -382,7 +382,8 @@ goto finish; error = !ath_hal_settpscale(sc->sc_ah, scale) ? EINVAL : - (sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS) : 0; + (sc->sc_running) ? ath_reset(sc, ATH_RESET_NOLOSS, + HAL_RESET_NORMAL) : 0; finish: ATH_LOCK(sc); @@ -443,7 +444,8 @@ error = EINVAL; goto finish; } - error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL) : 0; + error = sc->sc_running ? ath_reset(sc, ATH_RESET_FULL, + HAL_RESET_NORMAL) : 0; finish: ATH_LOCK(sc); @@ -670,7 +672,7 @@ * things in an inconsistent state. */ if (sc->sc_running) - ath_reset(sc, ATH_RESET_NOLOSS); + ath_reset(sc, ATH_RESET_NOLOSS, HAL_RESET_NORMAL); error = 0;