diff options
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 937 |
1 files changed, 97 insertions, 840 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 3787500..6e58896 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -73,7 +73,6 @@ __FBSDID("$FreeBSD$"); #include <machine/bus.h> #include <net/if.h> -#include <net/if_var.h> #include <net/if_dl.h> #include <net/if_media.h> #include <net/if_types.h> @@ -165,7 +164,6 @@ static void ath_bmiss_vap(struct ieee80211vap *); static void ath_bmiss_proc(void *, int); static void ath_key_update_begin(struct ieee80211vap *); static void ath_key_update_end(struct ieee80211vap *); -static void ath_update_mcast_hw(struct ath_softc *); static void ath_update_mcast(struct ifnet *); static void ath_update_promisc(struct ifnet *); static void ath_updateslot(struct ifnet *); @@ -240,14 +238,17 @@ SYSCTL_INT(_hw_ath, OID_AUTO, anical, CTLFLAG_RW, &ath_anicalinterval, 0, "ANI calibration (msecs)"); int ath_rxbuf = ATH_RXBUF; /* # rx buffers to allocate */ -SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RWTUN, &ath_rxbuf, +SYSCTL_INT(_hw_ath, OID_AUTO, rxbuf, CTLFLAG_RW, &ath_rxbuf, 0, "rx buffers allocated"); +TUNABLE_INT("hw.ath.rxbuf", &ath_rxbuf); int ath_txbuf = ATH_TXBUF; /* # tx buffers to allocate */ -SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RWTUN, &ath_txbuf, +SYSCTL_INT(_hw_ath, OID_AUTO, txbuf, CTLFLAG_RW, &ath_txbuf, 0, "tx buffers allocated"); +TUNABLE_INT("hw.ath.txbuf", &ath_txbuf); int ath_txbuf_mgmt = ATH_MGMT_TXBUF; /* # mgmt tx buffers to allocate */ -SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RWTUN, &ath_txbuf_mgmt, +SYSCTL_INT(_hw_ath, OID_AUTO, txbuf_mgmt, CTLFLAG_RW, &ath_txbuf_mgmt, 0, "tx (mgmt) buffers allocated"); +TUNABLE_INT("hw.ath.txbuf_mgmt", &ath_txbuf_mgmt); int ath_bstuck_threshold = 4; /* max missed beacons */ SYSCTL_INT(_hw_ath, OID_AUTO, bstuck, CTLFLAG_RW, &ath_bstuck_threshold, @@ -277,293 +278,6 @@ ath_legacy_attach_comp_func(struct ath_softc *sc) } } -/* - * Set the target power mode. - * - * If this is called during a point in time where - * the hardware is being programmed elsewhere, it will - * simply store it away and update it when all current - * uses of the hardware are completed. - */ -void -_ath_power_setpower(struct ath_softc *sc, int power_state, const char *file, int line) -{ - ATH_LOCK_ASSERT(sc); - - sc->sc_target_powerstate = power_state; - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n", - __func__, - file, - line, - power_state, - sc->sc_powersave_refcnt); - - if (sc->sc_powersave_refcnt == 0 && - power_state != sc->sc_cur_powerstate) { - sc->sc_cur_powerstate = power_state; - ath_hal_setpower(sc->sc_ah, power_state); - - /* - * If the NIC is force-awake, then set the - * self-gen frame state appropriately. - * - * If the nic is in network sleep or full-sleep, - * we let the above call leave the self-gen - * state as "sleep". - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE && - sc->sc_target_selfgen_state != HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, - sc->sc_target_selfgen_state); - } - } -} - -/* - * Set the current self-generated frames state. - * - * This is separate from the target power mode. The chip may be - * awake but the desired state is "sleep", so frames sent to the - * destination has PWRMGT=1 in the 802.11 header. The NIC also - * needs to know to set PWRMGT=1 in self-generated frames. - */ -void -_ath_power_set_selfgen(struct ath_softc *sc, int power_state, const char *file, int line) -{ - - ATH_LOCK_ASSERT(sc); - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n", - __func__, - file, - line, - power_state, - sc->sc_target_selfgen_state); - - sc->sc_target_selfgen_state = power_state; - - /* - * If the NIC is force-awake, then set the power state. - * Network-state and full-sleep will already transition it to - * mark self-gen frames as sleeping - and we can't - * guarantee the NIC is awake to program the self-gen frame - * setting anyway. - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, power_state); - } -} - -/* - * Set the hardware power mode and take a reference. - * - * This doesn't update the target power mode in the driver; - * it just updates the hardware power state. - * - * XXX it should only ever force the hardware awake; it should - * never be called to set it asleep. - */ -void -_ath_power_set_power_state(struct ath_softc *sc, int power_state, const char *file, int line) -{ - ATH_LOCK_ASSERT(sc); - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) state=%d, refcnt=%d\n", - __func__, - file, - line, - power_state, - sc->sc_powersave_refcnt); - - sc->sc_powersave_refcnt++; - - if (power_state != sc->sc_cur_powerstate) { - ath_hal_setpower(sc->sc_ah, power_state); - sc->sc_cur_powerstate = power_state; - - /* - * Adjust the self-gen powerstate if appropriate. - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE && - sc->sc_target_selfgen_state != HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, - sc->sc_target_selfgen_state); - } - - } -} - -/* - * Restore the power save mode to what it once was. - * - * This will decrement the reference counter and once it hits - * zero, it'll restore the powersave state. - */ -void -_ath_power_restore_power_state(struct ath_softc *sc, const char *file, int line) -{ - - ATH_LOCK_ASSERT(sc); - - DPRINTF(sc, ATH_DEBUG_PWRSAVE, "%s: (%s:%d) refcnt=%d, target state=%d\n", - __func__, - file, - line, - sc->sc_powersave_refcnt, - sc->sc_target_powerstate); - - if (sc->sc_powersave_refcnt == 0) - device_printf(sc->sc_dev, "%s: refcnt=0?\n", __func__); - else - sc->sc_powersave_refcnt--; - - if (sc->sc_powersave_refcnt == 0 && - sc->sc_target_powerstate != sc->sc_cur_powerstate) { - sc->sc_cur_powerstate = sc->sc_target_powerstate; - ath_hal_setpower(sc->sc_ah, sc->sc_target_powerstate); - } - - /* - * Adjust the self-gen powerstate if appropriate. - */ - if (sc->sc_cur_powerstate == HAL_PM_AWAKE && - sc->sc_target_selfgen_state != HAL_PM_AWAKE) { - ath_hal_setselfgenpower(sc->sc_ah, - sc->sc_target_selfgen_state); - } - -} - -/* - * Configure the initial HAL configuration values based on bus - * specific parameters. - * - * Some PCI IDs and other information may need tweaking. - * - * XXX TODO: ath9k and the Atheros HAL only program comm2g_switch_enable - * if BT antenna diversity isn't enabled. - * - * So, let's also figure out how to enable BT diversity for AR9485. - */ -static void -ath_setup_hal_config(struct ath_softc *sc, HAL_OPS_CONFIG *ah_config) -{ - /* XXX TODO: only for PCI devices? */ - - if (sc->sc_pci_devinfo & (ATH_PCI_CUS198 | ATH_PCI_CUS230)) { - ah_config->ath_hal_ext_lna_ctl_gpio = 0x200; /* bit 9 */ - ah_config->ath_hal_ext_atten_margin_cfg = AH_TRUE; - ah_config->ath_hal_min_gainidx = AH_TRUE; - ah_config->ath_hal_ant_ctrl_comm2g_switch_enable = 0x000bbb88; - /* XXX low_rssi_thresh */ - /* XXX fast_div_bias */ - device_printf(sc->sc_dev, "configuring for %s\n", - (sc->sc_pci_devinfo & ATH_PCI_CUS198) ? - "CUS198" : "CUS230"); - } - - if (sc->sc_pci_devinfo & ATH_PCI_CUS217) - device_printf(sc->sc_dev, "CUS217 card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_CUS252) - device_printf(sc->sc_dev, "CUS252 card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_AR9565_1ANT) - device_printf(sc->sc_dev, "WB335 1-ANT card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_AR9565_2ANT) - device_printf(sc->sc_dev, "WB335 2-ANT card detected\n"); - - if (sc->sc_pci_devinfo & ATH_PCI_KILLER) - device_printf(sc->sc_dev, "Killer Wireless card detected\n"); - -#if 0 - /* - * Some WB335 cards do not support antenna diversity. Since - * we use a hardcoded value for AR9565 instead of using the - * EEPROM/OTP data, remove the combining feature from - * the HW capabilities bitmap. - */ - if (sc->sc_pci_devinfo & (ATH9K_PCI_AR9565_1ANT | ATH9K_PCI_AR9565_2ANT)) { - if (!(sc->sc_pci_devinfo & ATH9K_PCI_BT_ANT_DIV)) - pCap->hw_caps &= ~ATH9K_HW_CAP_ANT_DIV_COMB; - } - - if (sc->sc_pci_devinfo & ATH9K_PCI_BT_ANT_DIV) { - pCap->hw_caps |= ATH9K_HW_CAP_BT_ANT_DIV; - device_printf(sc->sc_dev, "Set BT/WLAN RX diversity capability\n"); - } -#endif - - if (sc->sc_pci_devinfo & ATH_PCI_D3_L1_WAR) { - ah_config->ath_hal_pcie_waen = 0x0040473b; - device_printf(sc->sc_dev, "Enable WAR for ASPM D3/L1\n"); - } - -#if 0 - if (sc->sc_pci_devinfo & ATH9K_PCI_NO_PLL_PWRSAVE) { - ah->config.no_pll_pwrsave = true; - device_printf(sc->sc_dev, "Disable PLL PowerSave\n"); - } -#endif - -} - -/* - * Attempt to fetch the MAC address from the kernel environment. - * - * Returns 0, macaddr in macaddr if successful; -1 otherwise. - */ -static int -ath_fetch_mac_kenv(struct ath_softc *sc, uint8_t *macaddr) -{ - char devid_str[32]; - int local_mac = 0; - char *local_macstr; - - /* - * Fetch from the kenv rather than using hints. - * - * Hints would be nice but the transition to dynamic - * hints/kenv doesn't happen early enough for this - * to work reliably (eg on anything embedded.) - */ - snprintf(devid_str, 32, "hint.%s.%d.macaddr", - device_get_name(sc->sc_dev), - device_get_unit(sc->sc_dev)); - - if ((local_macstr = getenv(devid_str)) != NULL) { - uint32_t tmpmac[ETHER_ADDR_LEN]; - int count; - int i; - - /* Have a MAC address; should use it */ - device_printf(sc->sc_dev, - "Overriding MAC address from environment: '%s'\n", - local_macstr); - - /* Extract out the MAC address */ - count = sscanf(local_macstr, "%x%*c%x%*c%x%*c%x%*c%x%*c%x", - &tmpmac[0], &tmpmac[1], - &tmpmac[2], &tmpmac[3], - &tmpmac[4], &tmpmac[5]); - if (count == 6) { - /* Valid! */ - local_mac = 1; - for (i = 0; i < ETHER_ADDR_LEN; i++) - macaddr[i] = tmpmac[i]; - } - /* Done! */ - freeenv(local_macstr); - local_macstr = NULL; - } - - if (local_mac) - return (0); - return (-1); -} - #define HAL_MODE_HT20 (HAL_MODE_11NG_HT20 | HAL_MODE_11NA_HT20) #define HAL_MODE_HT40 \ (HAL_MODE_11NG_HT40PLUS | HAL_MODE_11NG_HT40MINUS | \ @@ -579,7 +293,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) u_int wmodes; uint8_t macaddr[IEEE80211_ADDR_LEN]; int rx_chainmask, tx_chainmask; - HAL_OPS_CONFIG ah_config; DPRINTF(sc, ATH_DEBUG_ANY, "%s: devid 0x%x\n", __func__, devid); @@ -598,17 +311,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) device_get_unit(sc->sc_dev)); CURVNET_RESTORE(); - /* - * Configure the initial configuration data. - * - * This is stuff that may be needed early during attach - * rather than done via configuration calls later. - */ - bzero(&ah_config, sizeof(ah_config)); - ath_setup_hal_config(sc, &ah_config); - ah = ath_hal_attach(devid, sc, sc->sc_st, sc->sc_sh, - sc->sc_eepromdata, &ah_config, &status); + sc->sc_eepromdata, &status); if (ah == NULL) { if_printf(ifp, "unable to attach hardware; HAL status %u\n", status); @@ -636,10 +340,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ath_xmit_setup_legacy(sc); } - if (ath_hal_hasmybeacon(sc->sc_ah)) { - sc->sc_do_mybeacon = 1; - } - /* * Check if the MAC has multi-rate retry support. * We do this by trying to setup a fake extended @@ -904,8 +604,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) #ifdef ATH_ENABLE_DFS | IEEE80211_C_DFS /* Enable radar detection */ #endif - | IEEE80211_C_PMGT /* Station side power mgmt */ - | IEEE80211_C_SWSLEEP ; /* * Query the hal to figure out h/w crypto support. @@ -1203,14 +901,8 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) */ sc->sc_hasveol = ath_hal_hasveol(ah); - /* get mac address from kenv first, then hardware */ - if (ath_fetch_mac_kenv(sc, macaddr) == 0) { - /* Tell the HAL now about the new MAC */ - ath_hal_setmac(ah, macaddr); - } else { - ath_hal_getmac(ah, macaddr); - } - + /* get mac address from hardware */ + ath_hal_getmac(ah, macaddr); if (sc->sc_hasbmask) ath_hal_getbssidmask(ah, sc->sc_hwbssidmask); @@ -1301,14 +993,6 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) if (bootverbose) ieee80211_announce(ic); ath_announce(sc); - - /* - * Put it to sleep for now. - */ - ATH_LOCK(sc); - ath_power_setpower(sc, HAL_PM_FULL_SLEEP); - ATH_UNLOCK(sc); - return 0; bad2: ath_tx_cleanup(sc); @@ -1354,22 +1038,7 @@ ath_detach(struct ath_softc *sc) * it last * Other than that, it's straightforward... */ - - /* - * XXX Wake the hardware up first. ath_stop() will still - * wake it up first, but I'd rather do it here just to - * ensure it's awake. - */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - - /* - * Stop things cleanly. - */ ath_stop(ifp); - ieee80211_ifdetach(ifp->if_l2com); taskqueue_free(sc->sc_tq); #ifdef ATH_TX99_DIAG @@ -1732,10 +1401,6 @@ ath_vap_delete(struct ieee80211vap *vap) struct ath_hal *ah = sc->sc_ah; struct ath_vap *avp = ATH_VAP(vap); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - DPRINTF(sc, ATH_DEBUG_RESET, "%s: called\n", __func__); if (ifp->if_drv_flags & IFF_DRV_RUNNING) { /* @@ -1744,13 +1409,11 @@ ath_vap_delete(struct ieee80211vap *vap) * the vap state by any frames pending on the tx queues. */ ath_hal_intrset(ah, 0); /* disable interrupts */ + ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */ /* XXX Do all frames from all vaps/nodes need draining here? */ ath_stoprecv(sc, 1); /* stop recv side */ - ath_draintxq(sc, ATH_RESET_DEFAULT); /* stop hw xmit side */ } - /* .. leave the hardware awake for now. */ - ieee80211_vap_detach(vap); /* @@ -1838,9 +1501,6 @@ ath_vap_delete(struct ieee80211vap *vap) } ath_hal_intrset(ah, sc->sc_imask); } - - /* Ok, let the hardware asleep. */ - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); } @@ -1860,25 +1520,12 @@ ath_suspend(struct ath_softc *sc) * NB: don't worry about putting the chip in low power * mode; pci will power off our socket on suspend and * CardBus detaches the device. - * - * XXX TODO: well, that's great, except for non-cardbus - * devices! */ /* - * XXX This doesn't wait until all pending taskqueue - * items and parallel transmit/receive/other threads - * are running! - */ - ath_hal_intrset(sc->sc_ah, 0); - taskqueue_block(sc->sc_tq); - - ATH_LOCK(sc); - callout_stop(&sc->sc_cal_ch); - ATH_UNLOCK(sc); - - /* + * XXX ensure none of the taskqueues are running * XXX ensure sc_invalid is 1 + * XXX ensure the calibration callout is disabled */ /* Disable the PCIe PHY, complete with workarounds */ @@ -1899,12 +1546,8 @@ ath_reset_keycache(struct ath_softc *sc) struct ath_hal *ah = sc->sc_ah; int i; - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); for (i = 0; i < sc->sc_keymax; i++) ath_hal_keyreset(ah, i); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); ieee80211_crypto_reload_keys(ic); } @@ -1956,24 +1599,11 @@ ath_resume(struct ath_softc *sc) sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan); ath_hal_setchainmasks(sc->sc_ah, sc->sc_cur_txchainmask, sc->sc_cur_rxchainmask); - - /* Ensure we set the current power state to on */ - ATH_LOCK(sc); - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_hal_reset(ah, sc->sc_opmode, sc->sc_curchan != NULL ? sc->sc_curchan : ic->ic_curchan, AH_FALSE, &status); ath_reset_keycache(sc); - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - /* Let DFS at it in case it's a DFS channel */ ath_dfs_radar_enable(sc, ic->ic_curchan); @@ -2001,10 +1631,6 @@ ath_resume(struct ath_softc *sc) if (sc->sc_resume_up) ieee80211_resume_all(ic); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - /* XXX beacons ? */ } @@ -2062,10 +1688,6 @@ ath_intr(void *arg) return; } - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - if ((ifp->if_flags & IFF_UP) == 0 || (ifp->if_drv_flags & IFF_DRV_RUNNING) == 0) { HAL_INT status; @@ -2075,10 +1697,6 @@ ath_intr(void *arg) ath_hal_getisr(ah, &status); /* clear ISR */ ath_hal_intrset(ah, 0); /* disable further intr's */ ATH_PCU_UNLOCK(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); return; } @@ -2118,11 +1736,6 @@ ath_intr(void *arg) /* Short-circuit un-handled interrupts */ if (status == 0x0) { ATH_PCU_UNLOCK(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - return; } @@ -2178,46 +1791,44 @@ ath_intr(void *arg) if (status & HAL_INT_RXEOL) { int imask; ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXEOL"); - if (! sc->sc_isedma) { - ATH_PCU_LOCK(sc); - /* - * NB: the hardware should re-read the link when - * RXE bit is written, but it doesn't work at - * least on older hardware revs. - */ - sc->sc_stats.ast_rxeol++; - /* - * Disable RXEOL/RXORN - prevent an interrupt - * storm until the PCU logic can be reset. - * In case the interface is reset some other - * way before "sc_kickpcu" is called, don't - * modify sc_imask - that way if it is reset - * by a call to ath_reset() somehow, the - * interrupt mask will be correctly reprogrammed. - */ - imask = sc->sc_imask; - imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN); - ath_hal_intrset(ah, imask); - /* - * Only blank sc_rxlink if we've not yet kicked - * the PCU. - * - * This isn't entirely correct - the correct solution - * would be to have a PCU lock and engage that for - * the duration of the PCU fiddling; which would include - * running the RX process. Otherwise we could end up - * messing up the RX descriptor chain and making the - * RX desc list much shorter. - */ - if (! sc->sc_kickpcu) - sc->sc_rxlink = NULL; - sc->sc_kickpcu = 1; - ATH_PCU_UNLOCK(sc); - } + ATH_PCU_LOCK(sc); /* - * Enqueue an RX proc to handle whatever + * NB: the hardware should re-read the link when + * RXE bit is written, but it doesn't work at + * least on older hardware revs. + */ + sc->sc_stats.ast_rxeol++; + /* + * Disable RXEOL/RXORN - prevent an interrupt + * storm until the PCU logic can be reset. + * In case the interface is reset some other + * way before "sc_kickpcu" is called, don't + * modify sc_imask - that way if it is reset + * by a call to ath_reset() somehow, the + * interrupt mask will be correctly reprogrammed. + */ + imask = sc->sc_imask; + imask &= ~(HAL_INT_RXEOL | HAL_INT_RXORN); + ath_hal_intrset(ah, imask); + /* + * Only blank sc_rxlink if we've not yet kicked + * the PCU. + * + * This isn't entirely correct - the correct solution + * would be to have a PCU lock and engage that for + * the duration of the PCU fiddling; which would include + * running the RX process. Otherwise we could end up + * messing up the RX descriptor chain and making the + * RX desc list much shorter. + */ + if (! sc->sc_kickpcu) + sc->sc_rxlink = NULL; + sc->sc_kickpcu = 1; + ATH_PCU_UNLOCK(sc); + /* + * Enqueue an RX proc, to handled whatever * is in the RX queue. - * This will then kick the PCU if required. + * This will then kick the PCU. */ sc->sc_rx.recv_sched(sc, 1); } @@ -2291,18 +1902,10 @@ ath_intr(void *arg) ATH_KTR(sc, ATH_KTR_ERROR, 0, "ath_intr: RXORN"); sc->sc_stats.ast_rxorn++; } - if (status & HAL_INT_TSFOOR) { - device_printf(sc->sc_dev, "%s: TSFOOR\n", __func__); - sc->sc_syncbeacon = 1; - } } ATH_PCU_LOCK(sc); sc->sc_intr_cnt--; ATH_PCU_UNLOCK(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } static void @@ -2333,8 +1936,6 @@ ath_fatal_proc(void *arg, int pending) static void ath_bmiss_vap(struct ieee80211vap *vap) { - struct ath_softc *sc = vap->iv_ic->ic_ifp->if_softc; - /* * Workaround phantom bmiss interrupts by sanity-checking * the time of our last rx'd frame. If it is within the @@ -2343,16 +1944,6 @@ ath_bmiss_vap(struct ieee80211vap *vap) * be dispatched up for processing. Note this applies only * for h/w beacon miss events. */ - - /* - * XXX TODO: Just read the TSF during the interrupt path; - * that way we don't have to wake up again just to read it - * again. - */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - if ((vap->iv_flags_ext & IEEE80211_FEXT_SWBMISS) == 0) { struct ifnet *ifp = vap->iv_ic->ic_ifp; struct ath_softc *sc = ifp->if_softc; @@ -2370,32 +1961,12 @@ ath_bmiss_vap(struct ieee80211vap *vap) if (tsf - lastrx <= bmisstimeout) { sc->sc_stats.ast_bmiss_phantom++; - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - return; } } - - /* - * There's no need to keep the hardware awake during the call - * to av_bmiss(). - */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - /* - * Attempt to force a beacon resync. - */ - sc->sc_syncbeacon = 1; - ATH_VAP(vap)->av_bmiss(vap); } -/* XXX this needs a force wakeup! */ int ath_hal_gethangstate(struct ath_hal *ah, uint32_t mask, uint32_t *hangs) { @@ -2418,12 +1989,6 @@ ath_bmiss_proc(void *arg, int pending) DPRINTF(sc, ATH_DEBUG_ANY, "%s: pending %u\n", __func__, pending); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - - ath_beacon_miss(sc); - /* * Do a reset upon any becaon miss event. * @@ -2437,13 +2002,6 @@ ath_bmiss_proc(void *arg, int pending) ath_reset(ifp, ATH_RESET_NOLOSS); ieee80211_beacon_miss(ifp->if_l2com); } - - /* Force a beacon resync, in case they've drifted */ - sc->sc_syncbeacon = 1; - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } /* @@ -2483,13 +2041,6 @@ ath_init(void *arg) ATH_LOCK(sc); /* - * Force the sleep state awake. - */ - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - - /* * Stop anything previously setup. This is safe * whether this is the first time through or not. */ @@ -2506,19 +2057,12 @@ ath_init(void *arg) ath_update_chainmasks(sc, ic->ic_curchan); 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_FALSE, &status)) { if_printf(ifp, "unable to reset hardware; hal status %u\n", status); ATH_UNLOCK(sc); return; } - - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - ath_chan_change(sc, ic->ic_curchan); /* Let DFS at it in case it's a DFS channel */ @@ -2546,11 +2090,11 @@ ath_init(void *arg) * state cached in the driver. */ sc->sc_diversity = ath_hal_getdiversity(ah); - sc->sc_lastlongcal = ticks; + sc->sc_lastlongcal = 0; sc->sc_resetcal = 1; sc->sc_lastcalreset = 0; - sc->sc_lastani = ticks; - sc->sc_lastshortcal = ticks; + sc->sc_lastani = 0; + sc->sc_lastshortcal = 0; sc->sc_doresetcal = AH_FALSE; /* * Beacon timers were cleared here; give ath_newstate() @@ -2568,7 +2112,6 @@ ath_init(void *arg) */ if (ath_startrecv(sc) != 0) { if_printf(ifp, "unable to start recv logic\n"); - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); return; } @@ -2577,7 +2120,8 @@ ath_init(void *arg) * Enable interrupts. */ sc->sc_imask = HAL_INT_RX | HAL_INT_TX - | HAL_INT_RXORN | HAL_INT_TXURN + | HAL_INT_RXEOL | HAL_INT_RXORN + | HAL_INT_TXURN | HAL_INT_FATAL | HAL_INT_GLOBAL; /* @@ -2588,29 +2132,12 @@ ath_init(void *arg) sc->sc_imask |= (HAL_INT_RXHP | HAL_INT_RXLP); /* - * If we're an EDMA NIC, we don't care about RXEOL. - * Writing a new descriptor in will simply restart - * RX DMA. - */ - if (! sc->sc_isedma) - sc->sc_imask |= HAL_INT_RXEOL; - - /* * Enable MIB interrupts when there are hardware phy counters. * Note we only do this (at the moment) for station mode. */ if (sc->sc_needmib && ic->ic_opmode == IEEE80211_M_STA) sc->sc_imask |= HAL_INT_MIB; - /* - * XXX add capability for this. - * - * If we're in STA mode (and maybe IBSS?) then register for - * TSFOOR interrupts. - */ - if (ic->ic_opmode == IEEE80211_M_STA) - sc->sc_imask |= HAL_INT_TSFOOR; - /* Enable global TX timeout and carrier sense timeout if available */ if (ath_hal_gtxto_supported(ah)) sc->sc_imask |= HAL_INT_GTT; @@ -2622,7 +2149,6 @@ ath_init(void *arg) callout_reset(&sc->sc_wd_ch, hz, ath_watchdog, sc); ath_hal_intrset(ah, sc->sc_imask); - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); #ifdef ATH_TX99_DIAG @@ -2643,12 +2169,6 @@ ath_stop_locked(struct ifnet *ifp) __func__, sc->sc_invalid, ifp->if_flags); ATH_LOCK_ASSERT(sc); - - /* - * Wake the hardware up before fiddling with it. - */ - ath_power_set_power_state(sc, HAL_PM_AWAKE); - if (ifp->if_drv_flags & IFF_DRV_RUNNING) { /* * Shutdown the hardware and driver: @@ -2681,29 +2201,17 @@ ath_stop_locked(struct ifnet *ifp) } ath_hal_intrset(ah, 0); } - /* XXX we should stop RX regardless of whether it's valid */ + ath_draintxq(sc, ATH_RESET_DEFAULT); if (!sc->sc_invalid) { ath_stoprecv(sc, 1); ath_hal_phydisable(ah); } else sc->sc_rxlink = NULL; - ath_draintxq(sc, ATH_RESET_DEFAULT); ath_beacon_free(sc); /* XXX not needed */ } - - /* And now, restore the current power state */ - ath_power_restore_power_state(sc); } -/* - * Wait until all pending TX/RX has completed. - * - * This waits until all existing transmit, receive and interrupts - * have completed. It's assumed that the caller has first - * grabbed the reset lock so it doesn't try to do overlapping - * chip resets. - */ -#define MAX_TXRX_ITERATIONS 100 +#define MAX_TXRX_ITERATIONS 1000 static void ath_txrx_stop_locked(struct ath_softc *sc) { @@ -2722,8 +2230,7 @@ ath_txrx_stop_locked(struct ath_softc *sc) sc->sc_txstart_cnt || sc->sc_intr_cnt) { if (i <= 0) break; - msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop", - msecs_to_ticks(10)); + msleep(sc, &sc->sc_pcu_mtx, 0, "ath_txrx_stop", 1); i--; } @@ -2770,7 +2277,7 @@ ath_txrx_start(struct ath_softc *sc) * Another, cleaner way should be found to serialise all of * these operations. */ -#define MAX_RESET_ITERATIONS 25 +#define MAX_RESET_ITERATIONS 10 static int ath_reset_grablock(struct ath_softc *sc, int dowait) { @@ -2788,11 +2295,7 @@ ath_reset_grablock(struct ath_softc *sc, int dowait) break; } ATH_PCU_UNLOCK(sc); - /* - * 1 tick is likely not enough time for long calibrations - * to complete. So we should wait quite a while. - */ - pause("ath_reset_grablock", msecs_to_ticks(100)); + pause("ath_reset_grablock", 1); i--; ATH_PCU_LOCK(sc); } while (i > 0); @@ -2857,13 +2360,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Try to (stop any further TX/RX from occuring */ taskqueue_block(sc->sc_tq); - /* - * Wake the hardware up. - */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_PCU_LOCK(sc); /* @@ -2889,6 +2385,13 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ATH_PCU_UNLOCK(sc); /* + * Should now wait for pending TX/RX to complete + * and block future ones from occuring. This needs to be + * done before the TX queue is drained. + */ + ath_draintxq(sc, reset_type); /* stop xmit side */ + + /* * Regardless of whether we're doing a no-loss flush or * not, stop the PCU and handle what's in the RX queue. * That way frames aren't dropped which shouldn't be. @@ -2896,13 +2399,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ath_stoprecv(sc, (reset_type != ATH_RESET_NOLOSS)); ath_rx_flush(sc); - /* - * Should now wait for pending TX/RX to complete - * and block future ones from occuring. This needs to be - * done before the TX queue is drained. - */ - ath_draintxq(sc, reset_type); /* stop xmit side */ - ath_settkipmic(sc); /* configure TKIP MIC handling */ /* NB: indicate channel change so we do a full reset */ ath_update_chainmasks(sc, ic->ic_curchan); @@ -2913,11 +2409,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) __func__, status); sc->sc_diversity = ath_hal_getdiversity(ah); - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - /* Let DFS at it in case it's a DFS channel */ ath_dfs_radar_enable(sc, ic->ic_curchan); @@ -2963,13 +2454,9 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) * reset counter - this way ath_intr() doesn't end up * disabling interrupts without a corresponding enable * in the rest or channel change path. - * - * Grab the TX reference in case we need to transmit. - * That way a parallel transmit doesn't. */ ATH_PCU_LOCK(sc); sc->sc_inreset_cnt--; - sc->sc_txstart_cnt++; /* XXX only do this if sc_inreset_cnt == 0? */ ath_hal_intrset(ah, sc->sc_imask); ATH_PCU_UNLOCK(sc); @@ -2986,8 +2473,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Restart TX/RX as needed */ ath_txrx_start(sc); - /* XXX TODO: we need to hold the tx refcount here! */ - /* Restart TX completion and pending TX */ if (reset_type == ATH_RESET_NOLOSS) { for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { @@ -3012,14 +2497,6 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) ifp->if_drv_flags &= ~IFF_DRV_OACTIVE; IF_UNLOCK(&ifp->if_snd); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - - ATH_PCU_LOCK(sc); - sc->sc_txstart_cnt--; - ATH_PCU_UNLOCK(sc); - /* Handle any frames in the TX queue */ /* * XXX should this be done by the caller, rather than @@ -3160,7 +2637,6 @@ ath_buf_clone(struct ath_softc *sc, struct ath_buf *bf) tbf->bf_status = bf->bf_status; tbf->bf_m = bf->bf_m; tbf->bf_node = bf->bf_node; - KASSERT((bf->bf_node != NULL), ("%s: bf_node=NULL!", __func__)); /* will be setup by the chain/setup function */ tbf->bf_lastds = NULL; /* for now, last == self */ @@ -3262,11 +2738,6 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) sc->sc_txstart_cnt++; ATH_PCU_UNLOCK(sc); - /* Wake the hardware up already */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: start"); /* * Grab the TX lock - it's ok to do this here; we haven't @@ -3375,7 +2846,7 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) DPRINTF(sc, ATH_DEBUG_XMIT, "%s: out of txfrag buffers\n", __func__); sc->sc_stats.ast_tx_nofrag++; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; ath_freetx(m); goto bad; } @@ -3423,7 +2894,7 @@ ath_transmit(struct ifnet *ifp, struct mbuf *m) * * XXX should use atomics? */ - if_inc_counter(ifp, IFCOUNTER_OPACKETS, 1); + ifp->if_opackets++; nextfrag: /* * Pass the frame to the h/w for transmission. @@ -3443,7 +2914,7 @@ nextfrag: next = m->m_nextpkt; if (ath_tx_start(sc, ni, bf, m)) { bad: - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; reclaim: bf->bf_m = NULL; bf->bf_node = NULL; @@ -3500,11 +2971,6 @@ finish: sc->sc_txstart_cnt--; ATH_PCU_UNLOCK(sc); - /* Sleep the hardware if required */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TX, 0, "ath_transmit: finished"); return (retval); @@ -3532,6 +2998,7 @@ ath_key_update_begin(struct ieee80211vap *vap) DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); taskqueue_block(sc->sc_tq); + IF_LOCK(&ifp->if_snd); /* NB: doesn't block mgmt frames */ } static void @@ -3541,6 +3008,7 @@ ath_key_update_end(struct ieee80211vap *vap) struct ath_softc *sc = ifp->if_softc; DPRINTF(sc, ATH_DEBUG_KEYCACHE, "%s:\n", __func__); + IF_UNLOCK(&ifp->if_snd); taskqueue_unblock(sc->sc_tq); } @@ -3551,25 +3019,16 @@ ath_update_promisc(struct ifnet *ifp) u_int32_t rfilt; /* configure rx filter */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); rfilt = ath_calcrxfilter(sc); ath_hal_setrxfilter(sc->sc_ah, rfilt); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); DPRINTF(sc, ATH_DEBUG_MODE, "%s: RX filter 0x%x\n", __func__, rfilt); } -/* - * Driver-internal mcast update call. - * - * Assumes the hardware is already awake. - */ static void -ath_update_mcast_hw(struct ath_softc *sc) +ath_update_mcast(struct ifnet *ifp) { - struct ifnet *ifp = sc->sc_ifp; + struct ath_softc *sc = ifp->if_softc; u_int32_t mfilt[2]; /* calculate and install multicast filter */ @@ -3597,33 +3056,11 @@ ath_update_mcast_hw(struct ath_softc *sc) if_maddr_runlock(ifp); } else mfilt[0] = mfilt[1] = ~0; - ath_hal_setmcastfilter(sc->sc_ah, mfilt[0], mfilt[1]); - DPRINTF(sc, ATH_DEBUG_MODE, "%s: MC filter %08x:%08x\n", __func__, mfilt[0], mfilt[1]); } -/* - * Called from the net80211 layer - force the hardware - * awake before operating. - */ -static void -ath_update_mcast(struct ifnet *ifp) -{ - struct ath_softc *sc = ifp->if_softc; - - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - - ath_update_mcast_hw(sc); - - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); -} - void ath_mode_init(struct ath_softc *sc) { @@ -3649,7 +3086,7 @@ ath_mode_init(struct ath_softc *sc) ath_hal_setmac(ah, IF_LLADDR(ifp)); /* calculate and install multicast filter */ - ath_update_mcast_hw(sc); + ath_update_mcast(ifp); } /* @@ -3681,13 +3118,8 @@ ath_setslottime(struct ath_softc *sc) __func__, ic->ic_curchan->ic_freq, ic->ic_curchan->ic_flags, ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long", usec); - /* Wake up the hardware first before updating the slot time */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_hal_setslottime(ah, usec); - ath_power_restore_power_state(sc); sc->sc_updateslot = OK; - ATH_UNLOCK(sc); } /* @@ -3704,8 +3136,6 @@ ath_updateslot(struct ifnet *ifp) * When not coordinating the BSS, change the hardware * immediately. For other operation we defer the change * until beacon updates have propagated to the stations. - * - * XXX sc_updateslot isn't changed behind a lock? */ if (ic->ic_opmode == IEEE80211_M_HOSTAP || ic->ic_opmode == IEEE80211_M_MBSS) @@ -4611,12 +4041,14 @@ ath_tx_process_buf_completion(struct ath_softc *sc, struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf) { struct ieee80211_node *ni = bf->bf_node; + struct ath_node *an = NULL; ATH_TX_UNLOCK_ASSERT(sc); ATH_TXQ_UNLOCK_ASSERT(txq); /* If unicast frame, update general statistics */ if (ni != NULL) { + an = ATH_NODE(ni); /* update statistics */ ath_tx_update_stats(sc, ts, bf); } @@ -4825,10 +4257,6 @@ ath_tx_proc_q0(void *arg, int npending) sc->sc_txq_active &= ~txqs; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc_q0: txqs=0x%08x", txqs); @@ -4849,10 +4277,6 @@ ath_tx_proc_q0(void *arg, int npending) sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ath_tx_kick(sc); } @@ -4874,10 +4298,6 @@ ath_tx_proc_q0123(void *arg, int npending) sc->sc_txq_active &= ~txqs; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc_q0123: txqs=0x%08x", txqs); @@ -4910,10 +4330,6 @@ ath_tx_proc_q0123(void *arg, int npending) sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ath_tx_kick(sc); } @@ -4934,10 +4350,6 @@ ath_tx_proc(void *arg, int npending) sc->sc_txq_active &= ~txqs; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_KTR(sc, ATH_KTR_TXCOMP, 1, "ath_tx_proc: txqs=0x%08x", txqs); /* @@ -4963,10 +4375,6 @@ ath_tx_proc(void *arg, int npending) sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ath_tx_kick(sc); } #undef TXQACTIVE @@ -4993,10 +4401,6 @@ ath_txq_sched_tasklet(void *arg, int npending) sc->sc_txproc_cnt++; ATH_PCU_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ATH_TX_LOCK(sc); for (i = 0; i < HAL_NUM_TX_QUEUES; i++) { if (ATH_TXQ_SETUP(sc, i)) { @@ -5005,10 +4409,6 @@ ath_txq_sched_tasklet(void *arg, int npending) } ATH_TX_UNLOCK(sc); - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - ATH_PCU_LOCK(sc); sc->sc_txproc_cnt--; ATH_PCU_UNLOCK(sc); @@ -5516,15 +4916,14 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ATH_PCU_LOCK(sc); - /* Disable interrupts */ - ath_hal_intrset(ah, 0); - /* Stop new RX/TX/interrupt completion */ if (ath_reset_grablock(sc, 1) == 0) { device_printf(sc->sc_dev, "%s: concurrent reset! Danger!\n", __func__); } + ath_hal_intrset(ah, 0); + /* Stop pending RX/TX completion */ ath_txrx_stop_locked(sc); @@ -5568,11 +4967,6 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) } sc->sc_diversity = ath_hal_getdiversity(ah); - ATH_RX_LOCK(sc); - sc->sc_rx_stopped = 1; - sc->sc_rx_resetted = 1; - ATH_RX_UNLOCK(sc); - /* Let DFS at it in case it's a DFS channel */ ath_dfs_radar_enable(sc, chan); @@ -5662,17 +5056,6 @@ ath_calibrate(void *arg) HAL_BOOL aniCal, shortCal = AH_FALSE; int nextcal; - ATH_LOCK_ASSERT(sc); - - /* - * Force the hardware awake for ANI work. - */ - ath_power_set_power_state(sc, HAL_PM_AWAKE); - - /* Skip trying to do this if we're in reset */ - if (sc->sc_inreset_cnt) - goto restart; - if (ic->ic_flags & IEEE80211_F_SCAN) /* defer, off channel */ goto restart; longCal = (ticks - sc->sc_lastlongcal >= ath_longcalinterval*hz); @@ -5702,7 +5085,6 @@ ath_calibrate(void *arg) sc->sc_doresetcal = AH_TRUE; taskqueue_enqueue(sc->sc_tq, &sc->sc_resettask); callout_reset(&sc->sc_cal_ch, 1, ath_calibrate, sc); - ath_power_restore_power_state(sc); return; } /* @@ -5774,10 +5156,6 @@ restart: __func__); /* NB: don't rearm timer */ } - /* - * Restore power state now that we're done. - */ - ath_power_restore_power_state(sc); } static void @@ -5863,10 +5241,6 @@ ath_set_channel(struct ieee80211com *ic) struct ifnet *ifp = ic->ic_ifp; struct ath_softc *sc = ifp->if_softc; - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - (void) ath_chan_set(sc, ic->ic_curchan); /* * If we are returning to our bss channel then mark state @@ -5877,7 +5251,6 @@ ath_set_channel(struct ieee80211com *ic) ATH_LOCK(sc); if (!sc->sc_scanning && ic->ic_curchan == ic->ic_bsschan) sc->sc_syncbeacon = 1; - ath_power_restore_power_state(sc); ATH_UNLOCK(sc); } @@ -5910,7 +5283,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) int i, error, stamode; u_int32_t rfilt; int csa_run_transition = 0; - enum ieee80211_state ostate = vap->iv_state; static const HAL_LED_STATE leds[] = { HAL_LED_INIT, /* IEEE80211_S_INIT */ @@ -5924,7 +5296,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) }; DPRINTF(sc, ATH_DEBUG_STATE, "%s: %s -> %s\n", __func__, - ieee80211_state_name[ostate], + ieee80211_state_name[vap->iv_state], ieee80211_state_name[nstate]); /* @@ -5936,34 +5308,10 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) */ IEEE80211_LOCK_ASSERT(ic); - /* Before we touch the hardware - wake it up */ - ATH_LOCK(sc); - /* - * If the NIC is in anything other than SLEEP state, - * we need to ensure that self-generated frames are - * set for PWRMGT=0. Otherwise we may end up with - * strange situations. - * - * XXX TODO: is this actually the case? :-) - */ - if (nstate != IEEE80211_S_SLEEP) - ath_power_setselfgen(sc, HAL_PM_AWAKE); - - /* - * Now, wake the thing up. - */ - ath_power_set_power_state(sc, HAL_PM_AWAKE); - - /* - * And stop the calibration callout whilst we have - * ATH_LOCK held. - */ - callout_stop(&sc->sc_cal_ch); - ATH_UNLOCK(sc); - - if (ostate == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN) + if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN) csa_run_transition = 1; + callout_drain(&sc->sc_cal_ch); ath_hal_setledstate(ah, leds[nstate]); /* set LED */ if (nstate == IEEE80211_S_SCAN) { @@ -5973,13 +5321,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * [re]setup beacons. Unblock the task q thread so * deferred interrupt processing is done. */ - - /* Ensure we stay awake during scan */ - ATH_LOCK(sc); - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - ath_hal_intrset(ah, sc->sc_imask &~ (HAL_INT_SWBA | HAL_INT_BMISS)); sc->sc_imask &= ~(HAL_INT_SWBA | HAL_INT_BMISS); @@ -5992,11 +5333,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) stamode = (vap->iv_opmode == IEEE80211_M_STA || vap->iv_opmode == IEEE80211_M_AHDEMO || vap->iv_opmode == IEEE80211_M_IBSS); - - /* - * XXX Dont need to do this (and others) if we've transitioned - * from SLEEP->RUN. - */ if (stamode && nstate == IEEE80211_S_RUN) { sc->sc_curaid = ni->ni_associd; IEEE80211_ADDR_COPY(sc->sc_curbssid, ni->ni_bssid); @@ -6099,14 +5435,11 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * beacon to update the beacon timer and thus we * won't get notified of the missing beacons. */ - if (ostate != IEEE80211_S_RUN && - ostate != IEEE80211_S_SLEEP) { - DPRINTF(sc, ATH_DEBUG_BEACON, - "%s: STA; syncbeacon=1\n", __func__); - sc->sc_syncbeacon = 1; - - if (csa_run_transition) - ath_beacon_config(sc, vap); + sc->sc_syncbeacon = 1; +#if 0 + if (csa_run_transition) +#endif + ath_beacon_config(sc, vap); /* * PR: kern/175227 @@ -6120,8 +5453,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) * timer fires (too often), leading to a STA * disassociation. */ - sc->sc_beacons = 1; - } + sc->sc_beacons = 1; break; case IEEE80211_M_MONITOR: /* @@ -6147,14 +5479,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) sc->sc_halstats.ns_avgbrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_halstats.ns_avgrssi = ATH_RSSI_DUMMY_MARKER; sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; - - /* - * Force awake for RUN mode. - */ - ATH_LOCK(sc); - ath_power_setselfgen(sc, HAL_PM_AWAKE); - ath_power_setpower(sc, HAL_PM_AWAKE); - /* * Finally, start any timers and the task q thread * (in case we didn't go through SCAN state). @@ -6166,8 +5490,6 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) DPRINTF(sc, ATH_DEBUG_CALIBRATE, "%s: calibration disabled\n", __func__); } - ATH_UNLOCK(sc); - taskqueue_unblock(sc->sc_tq); } else if (nstate == IEEE80211_S_INIT) { /* @@ -6187,43 +5509,9 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg) #ifdef IEEE80211_SUPPORT_TDMA ath_hal_setcca(ah, AH_TRUE); #endif - } else if (nstate == IEEE80211_S_SLEEP) { - /* We're going to sleep, so transition appropriately */ - /* For now, only do this if we're a single STA vap */ - if (sc->sc_nvaps == 1 && - vap->iv_opmode == IEEE80211_M_STA) { - DPRINTF(sc, ATH_DEBUG_BEACON, "%s: syncbeacon=%d\n", __func__, sc->sc_syncbeacon); - ATH_LOCK(sc); - /* - * Always at least set the self-generated - * frame config to set PWRMGT=1. - */ - ath_power_setselfgen(sc, HAL_PM_NETWORK_SLEEP); - - /* - * If we're not syncing beacons, transition - * to NETWORK_SLEEP. - * - * We stay awake if syncbeacon > 0 in case - * we need to listen for some beacons otherwise - * our beacon timer config may be wrong. - */ - if (sc->sc_syncbeacon == 0) { - ath_power_setpower(sc, HAL_PM_NETWORK_SLEEP); - } - ATH_UNLOCK(sc); - } } bad: ieee80211_free_node(ni); - - /* - * Restore the power state - either to what it was, or - * to network_sleep if it's alright. - */ - ATH_LOCK(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); return error; } @@ -6278,16 +5566,7 @@ ath_newassoc(struct ieee80211_node *ni, int isnew) an->an_mcastrix = ath_tx_findrix(sc, tp->mcastrate); an->an_mgmtrix = ath_tx_findrix(sc, tp->mgmtrate); - DPRINTF(sc, ATH_DEBUG_NODE, "%s: %6D: reassoc; isnew=%d, is_powersave=%d\n", - __func__, - ni->ni_macaddr, - ":", - isnew, - an->an_is_powersave); - - ATH_NODE_LOCK(an); ath_rate_newassoc(sc, an, isnew); - ATH_NODE_UNLOCK(an); if (isnew && (vap->iv_flags & IEEE80211_F_PRIVACY) == 0 && sc->sc_hasclrkey && @@ -6527,14 +5806,10 @@ ath_watchdog(void *arg) struct ath_softc *sc = arg; int do_reset = 0; - ATH_LOCK_ASSERT(sc); - if (sc->sc_wd_timer != 0 && --sc->sc_wd_timer == 0) { struct ifnet *ifp = sc->sc_ifp; uint32_t hangs; - ath_power_set_power_state(sc, HAL_PM_AWAKE); - if (ath_hal_gethangstate(sc->sc_ah, 0xffff, &hangs) && hangs != 0) { if_printf(ifp, "%s hang detected (0x%x)\n", @@ -6542,10 +5817,8 @@ ath_watchdog(void *arg) } else if_printf(ifp, "device timeout\n"); do_reset = 1; - if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); + ifp->if_oerrors++; sc->sc_stats.ast_watchdog++; - - ath_power_restore_power_state(sc); } /* @@ -6643,13 +5916,6 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) goto bad; } } - - - ATH_LOCK(sc); - if (id != HAL_DIAG_REGS) - ath_power_set_power_state(sc, HAL_PM_AWAKE); - ATH_UNLOCK(sc); - if (ath_hal_getdiagstate(ah, id, indata, insize, &outdata, &outsize)) { if (outsize < ad->ad_out_size) ad->ad_out_size = outsize; @@ -6659,12 +5925,6 @@ ath_ioctl_diag(struct ath_softc *sc, struct ath_diag *ad) } else { error = EINVAL; } - - ATH_LOCK(sc); - if (id != HAL_DIAG_REGS) - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); - bad: if ((ad->ad_id & ATH_DIAG_IN) && indata != NULL) free(indata, M_TEMP); @@ -6687,17 +5947,14 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) switch (cmd) { case SIOCSIFFLAGS: + ATH_LOCK(sc); if (IS_RUNNING(ifp)) { /* * To avoid rescanning another access point, * do not call ath_init() here. Instead, * only reflect promisc mode settings. */ - ATH_LOCK(sc); - ath_power_set_power_state(sc, HAL_PM_AWAKE); ath_mode_init(sc); - ath_power_restore_power_state(sc); - ATH_UNLOCK(sc); } else if (ifp->if_flags & IFF_UP) { /* * Beware of being called during attach/detach @@ -6711,12 +5968,14 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) if (!sc->sc_invalid) ath_init(sc); /* XXX lose error */ } else { - ATH_LOCK(sc); ath_stop_locked(ifp); +#ifdef notyet + /* XXX must wakeup in places like ath_vap_delete */ if (!sc->sc_invalid) - ath_power_setpower(sc, HAL_PM_FULL_SLEEP); - ATH_UNLOCK(sc); + ath_hal_setpower(sc->sc_ah, HAL_PM_FULL_SLEEP); +#endif } + ATH_UNLOCK(sc); break; case SIOCGIFMEDIA: case SIOCSIFMEDIA: @@ -6724,10 +5983,8 @@ ath_ioctl(struct ifnet *ifp, u_long cmd, caddr_t data) break; case SIOCGATHSTATS: /* NB: embed these numbers to get a consistent view */ - sc->sc_stats.ast_tx_packets = if_get_counter_default(ifp, - IFCOUNTER_OPACKETS); - sc->sc_stats.ast_rx_packets = if_get_counter_default(ifp, - IFCOUNTER_IPACKETS); + sc->sc_stats.ast_tx_packets = ifp->if_opackets; + sc->sc_stats.ast_rx_packets = ifp->if_ipackets; sc->sc_stats.ast_tx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgtxrssi); sc->sc_stats.ast_rx_rssi = ATH_RSSI(sc->sc_halstats.ns_avgrssi); #ifdef IEEE80211_SUPPORT_TDMA @@ -7084,7 +6341,7 @@ ath_tx_update_tim(struct ath_softc *sc, struct ieee80211_node *ni, /* * Don't bother grabbing the lock unless the queue is empty. */ - if (an->an_swq_depth != 0) + if (&an->an_swq_depth != 0) return; if (an->an_is_powersave && @@ -7254,6 +6511,6 @@ ath_node_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m) MODULE_VERSION(if_ath, 1); MODULE_DEPEND(if_ath, wlan, 1, 1, 1); /* 802.11 media layer */ -#if defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ) || defined(ATH_DEBUG_ALQ) +#if defined(IEEE80211_ALQ) || defined(AH_DEBUG_ALQ) MODULE_DEPEND(if_ath, alq, 1, 1, 1); #endif |