aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath9k/htc_drv_main.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/htc_drv_main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c104
1 files changed, 71 insertions, 33 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index eb7722b2cfc..ca7f3a78eb1 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -94,8 +94,11 @@ void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
if (--priv->ps_usecount != 0)
goto unlock;
- if (priv->ps_enabled)
+ if (priv->ps_idle)
+ ath9k_hw_setpower(priv->ah, ATH9K_PM_FULL_SLEEP);
+ else if (priv->ps_enabled)
ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
+
unlock:
mutex_unlock(&priv->htc_pm_lock);
}
@@ -125,7 +128,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
bool fastcc = true;
struct ieee80211_channel *channel = hw->conf.channel;
enum htc_phymode mode;
- u16 htc_mode;
+ __be16 htc_mode;
u8 cmd_rsp;
int ret;
@@ -153,7 +156,6 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
ath_print(common, ATH_DBG_FATAL,
"Unable to reset channel (%u Mhz) "
"reset status %d\n", channel->center_freq, ret);
- ath9k_htc_ps_restore(priv);
goto err;
}
@@ -378,7 +380,7 @@ static int ath9k_htc_init_rate(struct ath9k_htc_priv *priv,
priv->tgt_rate.sta_index = ista->index;
priv->tgt_rate.isnew = 1;
trate = priv->tgt_rate;
- priv->tgt_rate.capflags = caps;
+ priv->tgt_rate.capflags = cpu_to_be32(caps);
trate.capflags = cpu_to_be32(caps);
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
@@ -426,6 +428,7 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)
struct ath9k_htc_target_rate trate;
struct ath_common *common = ath9k_hw_common(priv->ah);
int ret;
+ u32 caps = be32_to_cpu(priv->tgt_rate.capflags);
u8 cmd_rsp;
memset(&trate, 0, sizeof(trate));
@@ -433,11 +436,12 @@ static void ath9k_htc_rc_update(struct ath9k_htc_priv *priv, bool is_cw40)
trate = priv->tgt_rate;
if (is_cw40)
- priv->tgt_rate.capflags |= WLAN_RC_40_FLAG;
+ caps |= WLAN_RC_40_FLAG;
else
- priv->tgt_rate.capflags &= ~WLAN_RC_40_FLAG;
+ caps &= ~WLAN_RC_40_FLAG;
- trate.capflags = cpu_to_be32(priv->tgt_rate.capflags);
+ priv->tgt_rate.capflags = cpu_to_be32(caps);
+ trate.capflags = cpu_to_be32(caps);
WMI_CMD_BUF(WMI_RC_RATE_UPDATE_CMDID, &trate);
if (ret) {
@@ -609,6 +613,9 @@ static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
len += snprintf(buf + len, sizeof(buf) - len,
"%20s : %10u\n", "SKBs completed",
priv->debug.tx_stats.skb_completed);
+ len += snprintf(buf + len, sizeof(buf) - len,
+ "%20s : %10u\n", "SKBs dropped",
+ priv->debug.tx_stats.skb_dropped);
return simple_read_from_buffer(user_buf, count, ppos, buf, len);
}
@@ -960,7 +967,6 @@ void ath9k_deinit_leds(struct ath9k_htc_priv *priv)
ath9k_unregister_led(&priv->tx_led);
ath9k_unregister_led(&priv->rx_led);
ath9k_unregister_led(&priv->radio_led);
- ath9k_hw_set_gpio(priv->ah, priv->ah->led_pin, 1);
}
void ath9k_init_leds(struct ath9k_htc_priv *priv)
@@ -1093,7 +1099,7 @@ fail_tx:
return 0;
}
-static int ath9k_htc_start(struct ieee80211_hw *hw)
+static int ath9k_htc_radio_enable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
@@ -1102,15 +1108,13 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
struct ath9k_channel *init_channel;
int ret = 0;
enum htc_phymode mode;
- u16 htc_mode;
+ __be16 htc_mode;
u8 cmd_rsp;
ath_print(common, ATH_DBG_CONFIG,
"Starting driver with initial channel: %d MHz\n",
curchan->center_freq);
- mutex_lock(&priv->mutex);
-
/* setup initial channel */
init_channel = ath9k_cmn_get_curchannel(hw, ah);
@@ -1123,7 +1127,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ath_print(common, ATH_DBG_FATAL,
"Unable to reset hardware; reset status %d "
"(freq %u MHz)\n", ret, curchan->center_freq);
- goto mutex_unlock;
+ return ret;
}
ath_update_txpow(priv);
@@ -1131,16 +1135,8 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
mode = ath9k_htc_get_curmode(priv, init_channel);
htc_mode = cpu_to_be16(mode);
WMI_CMD_BUF(WMI_SET_MODE_CMDID, &htc_mode);
- if (ret)
- goto mutex_unlock;
-
WMI_CMD(WMI_ATH_INIT_CMDID);
- if (ret)
- goto mutex_unlock;
-
WMI_CMD(WMI_START_RECV_CMDID);
- if (ret)
- goto mutex_unlock;
ath9k_host_rx_init(priv);
@@ -1153,12 +1149,22 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
ieee80211_wake_queues(hw);
-mutex_unlock:
+ return ret;
+}
+
+static int ath9k_htc_start(struct ieee80211_hw *hw)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+ int ret = 0;
+
+ mutex_lock(&priv->mutex);
+ ret = ath9k_htc_radio_enable(hw);
mutex_unlock(&priv->mutex);
+
return ret;
}
-static void ath9k_htc_stop(struct ieee80211_hw *hw)
+static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
{
struct ath9k_htc_priv *priv = hw->priv;
struct ath_hw *ah = priv->ah;
@@ -1166,14 +1172,18 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
int ret = 0;
u8 cmd_rsp;
- mutex_lock(&priv->mutex);
-
if (priv->op_flags & OP_INVALID) {
ath_print(common, ATH_DBG_ANY, "Device not present\n");
- mutex_unlock(&priv->mutex);
return;
}
+ /* Cancel all the running timers/work .. */
+ cancel_work_sync(&priv->ps_work);
+ cancel_delayed_work_sync(&priv->ath9k_ani_work);
+ cancel_delayed_work_sync(&priv->ath9k_aggr_work);
+ cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+ ath9k_led_stop_brightness(priv);
+
ath9k_htc_ps_wakeup(priv);
htc_stop(priv->htc);
WMI_CMD(WMI_DISABLE_INTR_CMDID);
@@ -1185,11 +1195,6 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
ath9k_htc_ps_restore(priv);
ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
- cancel_work_sync(&priv->ps_work);
- cancel_delayed_work_sync(&priv->ath9k_ani_work);
- cancel_delayed_work_sync(&priv->ath9k_aggr_work);
- cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
- ath9k_led_stop_brightness(priv);
skb_queue_purge(&priv->tx_queue);
/* Remove monitor interface here */
@@ -1203,11 +1208,20 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
}
priv->op_flags |= OP_INVALID;
- mutex_unlock(&priv->mutex);
ath_print(common, ATH_DBG_CONFIG, "Driver halt\n");
}
+static void ath9k_htc_stop(struct ieee80211_hw *hw)
+{
+ struct ath9k_htc_priv *priv = hw->priv;
+
+ mutex_lock(&priv->mutex);
+ ath9k_htc_radio_disable(hw);
+ mutex_unlock(&priv->mutex);
+}
+
+
static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -1321,6 +1335,23 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
mutex_lock(&priv->mutex);
+ if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+ bool enable_radio = false;
+ bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+
+ if (!idle && priv->ps_idle)
+ enable_radio = true;
+
+ priv->ps_idle = idle;
+
+ if (enable_radio) {
+ ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
+ ath9k_htc_radio_enable(hw);
+ ath_print(common, ATH_DBG_CONFIG,
+ "not-idle: enabling radio\n");
+ }
+ }
+
if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
struct ieee80211_channel *curchan = hw->conf.channel;
int pos = curchan->hw_value;
@@ -1364,6 +1395,13 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
}
}
+ if (priv->ps_idle) {
+ ath_print(common, ATH_DBG_CONFIG,
+ "idle: disabling radio\n");
+ ath9k_htc_radio_disable(hw);
+ }
+
+
mutex_unlock(&priv->mutex);
return 0;
@@ -1687,7 +1725,7 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
spin_unlock_bh(&priv->beacon_lock);
priv->op_flags |= OP_FULL_RESET;
if (priv->op_flags & OP_ASSOCIATED)
- ath9k_htc_beacon_config(priv, NULL);
+ ath9k_htc_beacon_config(priv, priv->vif);
ath_start_ani(priv);
mutex_unlock(&priv->mutex);
ath9k_htc_ps_restore(priv);