static void ath9k_htc_stop(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); int ret __attribute__ ((unused)); u8 cmd_rsp; mutex_lock(&priv->mutex); if (test_bit(ATH_OP_INVALID, &common->op_flags)) { ath_dbg(common, ANY, "Device not present\n"); mutex_unlock(&priv->mutex); return; } ath9k_htc_ps_wakeup(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); tasklet_kill(&priv->rx_tasklet); del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); ath9k_wmi_event_drain(priv); mutex_unlock(&priv->mutex); /* Cancel all the running timers/work .. */ cancel_work_sync(&priv->fatal_work); cancel_work_sync(&priv->ps_work); #ifdef CPTCFG_MAC80211_LEDS cancel_work_sync(&priv->led_work); #endif ath9k_htc_stop_ani(priv); mutex_lock(&priv->mutex); ath9k_htc_stop_btcoex(priv); /* Remove a monitor interface if it's present. */ if (priv->ah->is_monitoring) ath9k_htc_remove_monitor_interface(priv); ath9k_hw_phy_disable(ah); ath9k_hw_disable(ah); ath9k_htc_ps_restore(priv); ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); set_bit(ATH_OP_INVALID, &common->op_flags); ath_dbg(common, CONFIG, "Driver halt\n"); mutex_unlock(&priv->mutex); }
void ath9k_htc_reset(struct ath9k_htc_priv *priv) { struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_channel *channel = priv->hw->conf.chandef.chan; struct ath9k_hw_cal_data *caldata = NULL; enum htc_phymode mode; __be16 htc_mode; u8 cmd_rsp; int ret; mutex_lock(&priv->mutex); ath9k_htc_ps_wakeup(priv); ath9k_htc_stop_ani(priv); ieee80211_stop_queues(priv->hw); del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); ath9k_wmi_event_drain(priv); caldata = &priv->caldata; ret = ath9k_hw_reset(ah, ah->curchan, caldata, false); if (ret) { ath_err(common, "Unable to reset device (%u Mhz) reset status %d\n", channel->center_freq, ret); } ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, &priv->curtxpow); WMI_CMD(WMI_START_RECV_CMDID); ath9k_host_rx_init(priv); mode = ath9k_htc_get_curmode(priv, ah->curchan); htc_mode = cpu_to_be16(mode); WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); WMI_CMD(WMI_ENABLE_INTR_CMDID); htc_start(priv->htc); ath9k_htc_vif_reconfig(priv); ieee80211_wake_queues(priv->hw); mod_timer(&priv->tx.cleanup_timer, jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); ath9k_htc_ps_restore(priv); mutex_unlock(&priv->mutex); }
void ath9k_htc_radio_disable(struct ieee80211_hw *hw) { struct ath9k_htc_priv *priv = hw->priv; struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); int ret; u8 cmd_rsp; ath9k_htc_ps_wakeup(priv); /* Disable LED */ ath9k_hw_set_gpio(ah, ah->led_pin, 1); ath9k_hw_cfg_gpio_input(ah, ah->led_pin); WMI_CMD(WMI_DISABLE_INTR_CMDID); /* Stop TX */ ieee80211_stop_queues(hw); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); /* Stop RX */ WMI_CMD(WMI_STOP_RECV_CMDID); /* Clear the WMI event queue */ ath9k_wmi_event_drain(priv); /* * The MIB counters have to be disabled here, * since the target doesn't do it. */ ath9k_hw_disable_mib_counters(ah); if (!ah->curchan) ah->curchan = ath9k_cmn_get_curchannel(hw, ah); /* Reset the HW */ ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); if (ret) { ath_err(common, "Unable to reset hardware; reset status %d (freq %u MHz)\n", ret, ah->curchan->channel); } /* Disable the PHY */ ath9k_hw_phy_disable(ah); ath9k_htc_ps_restore(priv); ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP); }
static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, struct ieee80211_hw *hw, struct ath9k_channel *hchan) { struct ath_hw *ah = priv->ah; struct ath_common *common = ath9k_hw_common(ah); struct ieee80211_conf *conf = &common->hw->conf; bool fastcc; struct ieee80211_channel *channel = hw->conf.chandef.chan; struct ath9k_hw_cal_data *caldata = NULL; enum htc_phymode mode; __be16 htc_mode; u8 cmd_rsp; int ret; if (test_bit(ATH_OP_INVALID, &common->op_flags)) return -EIO; fastcc = !!(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL); ath9k_htc_ps_wakeup(priv); ath9k_htc_stop_ani(priv); del_timer_sync(&priv->tx.cleanup_timer); ath9k_htc_tx_drain(priv); WMI_CMD(WMI_DISABLE_INTR_CMDID); WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); WMI_CMD(WMI_STOP_RECV_CMDID); ath9k_wmi_event_drain(priv); ath_dbg(common, CONFIG, "(%u MHz) -> (%u MHz), HT: %d, HT40: %d fastcc: %d\n", priv->ah->curchan->channel, channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf), fastcc); if (!fastcc) caldata = &priv->caldata; ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); if (ret) { ath_err(common, "Unable to reset channel (%u Mhz) reset status %d\n", channel->center_freq, ret); goto err; } ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit, &priv->curtxpow); WMI_CMD(WMI_START_RECV_CMDID); if (ret) goto err; ath9k_host_rx_init(priv); mode = ath9k_htc_get_curmode(priv, hchan); htc_mode = cpu_to_be16(mode); WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode); if (ret) goto err; WMI_CMD(WMI_ENABLE_INTR_CMDID); if (ret) goto err; htc_start(priv->htc); if (!test_bit(ATH_OP_SCANNING, &common->op_flags) && !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) ath9k_htc_vif_reconfig(priv); mod_timer(&priv->tx.cleanup_timer, jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); err: ath9k_htc_ps_restore(priv); return ret; }