mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-13 10:02:38 +00:00
[ath] [ath_hal] Propagate the HAL_RESET_TYPE through to the chip reset; set it during ath_reset()
Although I added the reset type field to ath_hal_reset() years ago, I never finished adding it both throughout the HALs and in if_ath.c. This will eventually deprecate the ath_hal force_full_reset option because it can be requested at the driver layer. So: * Teach ar5416ChipReset() and ar9300_chip_reset() about the HAL type * Use it in ar5416Reset() and ar9300_reset() when doing a full chip reset * Extend ath_reset() to include the HAL_RESET_TYPE parameter added in the above functions * Use HAL_RESET_NORMAL in most calls to ath_reset() * .. but use HAL_RESET_BBPANIC for the BB panics, and HAL_RESET_FORCE_COLD during fatal, beacon miss and other hardware related hangs. This should be a glorified no-op outside of actual hardware issues. I've tested things with ath_hal force_full_reset set to 1 for years now, so I know that feature and a full reset works (albeit much slower than a warm reset!) and it does unwedge hardware. The eventual aim is to use this for all the places where the driver detects a potential hang as well as if long calibration - ie, noise floor calibration - fails to complete. That's one of the big hardware related things that causes station mode operation to hang without easy recovery. Differential Revision: https://reviews.freebsd.org/D24981
This commit is contained in:
parent
a639f9379b
commit
8c01c3dc46
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=361486
@ -1390,7 +1390,7 @@ extern void ar9300_wowoffload_download_ns_info(struct ath_hal *ah, u_int32_t id
|
||||
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 u_int16_t ar9300_is_single_ant_power_save_possible(struct ath_hal *ah);
|
||||
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,
|
||||
|
@ -543,6 +543,7 @@ ar9300_reset_freebsd(struct ath_hal *ah, HAL_OPMODE opmode,
|
||||
HAL_HT_EXTPROTSPACING_20, /* always 20Mhz channel spacing */
|
||||
bChannelChange,
|
||||
status,
|
||||
resetType,
|
||||
AH_FALSE); /* XXX should really extend ath_hal_reset() */
|
||||
|
||||
return (r);
|
||||
|
@ -2064,7 +2064,7 @@ ar9300_set_rf_mode(struct ath_hal *ah, struct ieee80211_channel *chan)
|
||||
* 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 @@ ar9300_chip_reset(struct ath_hal *ah, struct ieee80211_channel *chan)
|
||||
*/
|
||||
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 @@ 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_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 @@ ar9300_reset(struct ath_hal *ah, HAL_OPMODE opmode, struct ieee80211_channel *ch
|
||||
/* 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);
|
||||
}
|
||||
|
@ -306,7 +306,8 @@ extern HAL_BOOL ar5416PhyDisable(struct ath_hal *ah);
|
||||
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 *);
|
||||
|
@ -376,7 +376,7 @@ ar5416Attach(uint16_t devid, HAL_SOFTC sc,
|
||||
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;
|
||||
|
@ -170,13 +170,15 @@ ar5416Reset(struct ath_hal *ah, HAL_OPMODE opmode,
|
||||
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 @@ ar5416SetRfMode(struct ath_hal *ah, const struct ieee80211_channel *chan)
|
||||
* 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);
|
||||
/*
|
||||
@ -788,6 +791,13 @@ ar5416ChipReset(struct ath_hal *ah, const struct ieee80211_channel *chan)
|
||||
} 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 {
|
||||
if (!ar5416SetResetReg(ah, HAL_RESET_WARM))
|
||||
return AH_FALSE;
|
||||
|
@ -173,7 +173,7 @@ ar9130Attach(uint16_t devid, HAL_SOFTC sc,
|
||||
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;
|
||||
|
@ -200,7 +200,7 @@ ar9160Attach(uint16_t devid, HAL_SOFTC sc,
|
||||
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;
|
||||
|
@ -259,7 +259,7 @@ ar9280Attach(uint16_t devid, HAL_SOFTC sc,
|
||||
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;
|
||||
|
@ -249,7 +249,7 @@ ar9285Attach(uint16_t devid, HAL_SOFTC sc,
|
||||
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;
|
||||
|
@ -242,7 +242,7 @@ ar9287Attach(uint16_t devid, HAL_SOFTC sc,
|
||||
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;
|
||||
|
@ -2380,7 +2380,7 @@ ath_fatal_proc(void *arg, int pending)
|
||||
"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 @@ ath_bmiss_proc(void *arg, int pending)
|
||||
* 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 @@ ath_reset_grablock(struct ath_softc *sc, int dowait)
|
||||
* 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_reset(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
|
||||
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 @@ ath_reset_vap(struct ieee80211vap *vap, u_long cmd)
|
||||
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 @@ ath_reset_proc(void *arg, int pending)
|
||||
#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 @@ ath_bstuck_proc(void *arg, int pending)
|
||||
* 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 @@ ath_calibrate(void *arg)
|
||||
* 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;
|
||||
|
@ -58,7 +58,8 @@ extern void ath_freebuf(struct ath_softc *sc, struct ath_buf *bf);
|
||||
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,
|
||||
|
@ -382,7 +382,8 @@ ath_sysctl_tpscale(SYSCTL_HANDLER_ARGS)
|
||||
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 @@ ath_sysctl_rfkill(SYSCTL_HANDLER_ARGS)
|
||||
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 @@ ath_sysctl_intmit(SYSCTL_HANDLER_ARGS)
|
||||
* 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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user