aboutsummaryrefslogtreecommitdiffstats
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.c149
1 files changed, 128 insertions, 21 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 20a2c1341e20..eb7722b2cfcc 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -65,6 +65,56 @@ static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
65 return mode; 65 return mode;
66} 66}
67 67
68static bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
69 enum ath9k_power_mode mode)
70{
71 bool ret;
72
73 mutex_lock(&priv->htc_pm_lock);
74 ret = ath9k_hw_setpower(priv->ah, mode);
75 mutex_unlock(&priv->htc_pm_lock);
76
77 return ret;
78}
79
80void ath9k_htc_ps_wakeup(struct ath9k_htc_priv *priv)
81{
82 mutex_lock(&priv->htc_pm_lock);
83 if (++priv->ps_usecount != 1)
84 goto unlock;
85 ath9k_hw_setpower(priv->ah, ATH9K_PM_AWAKE);
86
87unlock:
88 mutex_unlock(&priv->htc_pm_lock);
89}
90
91void ath9k_htc_ps_restore(struct ath9k_htc_priv *priv)
92{
93 mutex_lock(&priv->htc_pm_lock);
94 if (--priv->ps_usecount != 0)
95 goto unlock;
96
97 if (priv->ps_enabled)
98 ath9k_hw_setpower(priv->ah, ATH9K_PM_NETWORK_SLEEP);
99unlock:
100 mutex_unlock(&priv->htc_pm_lock);
101}
102
103void ath9k_ps_work(struct work_struct *work)
104{
105 struct ath9k_htc_priv *priv =
106 container_of(work, struct ath9k_htc_priv,
107 ps_work);
108 ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
109
110 /* The chip wakes up after receiving the first beacon
111 while network sleep is enabled. For the driver to
112 be in sync with the hw, set the chip to awake and
113 only then set it to sleep.
114 */
115 ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
116}
117
68static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, 118static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
69 struct ieee80211_hw *hw, 119 struct ieee80211_hw *hw,
70 struct ath9k_channel *hchan) 120 struct ath9k_channel *hchan)
@@ -87,7 +137,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
87 137
88 /* Fiddle around with fastcc later on, for now just use full reset */ 138 /* Fiddle around with fastcc later on, for now just use full reset */
89 fastcc = false; 139 fastcc = false;
90 140 ath9k_htc_ps_wakeup(priv);
91 htc_stop(priv->htc); 141 htc_stop(priv->htc);
92 WMI_CMD(WMI_DISABLE_INTR_CMDID); 142 WMI_CMD(WMI_DISABLE_INTR_CMDID);
93 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); 143 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
@@ -103,6 +153,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
103 ath_print(common, ATH_DBG_FATAL, 153 ath_print(common, ATH_DBG_FATAL,
104 "Unable to reset channel (%u Mhz) " 154 "Unable to reset channel (%u Mhz) "
105 "reset status %d\n", channel->center_freq, ret); 155 "reset status %d\n", channel->center_freq, ret);
156 ath9k_htc_ps_restore(priv);
106 goto err; 157 goto err;
107 } 158 }
108 159
@@ -128,6 +179,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
128 179
129 priv->op_flags &= ~OP_FULL_RESET; 180 priv->op_flags &= ~OP_FULL_RESET;
130err: 181err:
182 ath9k_htc_ps_restore(priv);
131 return ret; 183 return ret;
132} 184}
133 185
@@ -412,32 +464,31 @@ static int ath9k_htc_aggr_oper(struct ath9k_htc_priv *priv,
412 if (tid > ATH9K_HTC_MAX_TID) 464 if (tid > ATH9K_HTC_MAX_TID)
413 return -EINVAL; 465 return -EINVAL;
414 466
467 memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr));
468
415 rcu_read_lock(); 469 rcu_read_lock();
470
471 /* Check if we are able to retrieve the station */
416 sta = ieee80211_find_sta(vif, sta_addr); 472 sta = ieee80211_find_sta(vif, sta_addr);
417 if (sta) { 473 if (!sta) {
418 ista = (struct ath9k_htc_sta *) sta->drv_priv;
419 } else {
420 rcu_read_unlock(); 474 rcu_read_unlock();
421 return -EINVAL; 475 return -EINVAL;
422 } 476 }
423 477
424 if (!ista) { 478 ista = (struct ath9k_htc_sta *) sta->drv_priv;
425 rcu_read_unlock();
426 return -EINVAL;
427 }
428 479
429 memset(&aggr, 0, sizeof(struct ath9k_htc_target_aggr)); 480 if (oper)
481 ista->tid_state[tid] = AGGR_START;
482 else
483 ista->tid_state[tid] = AGGR_STOP;
430 484
431 aggr.sta_index = ista->index; 485 aggr.sta_index = ista->index;
486
432 rcu_read_unlock(); 487 rcu_read_unlock();
488
433 aggr.tidno = tid; 489 aggr.tidno = tid;
434 aggr.aggr_enable = oper; 490 aggr.aggr_enable = oper;
435 491
436 if (oper)
437 ista->tid_state[tid] = AGGR_START;
438 else
439 ista->tid_state[tid] = AGGR_STOP;
440
441 WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr); 492 WMI_CMD_BUF(WMI_TX_AGGR_ENABLE_CMDID, &aggr);
442 if (ret) 493 if (ret)
443 ath_print(common, ATH_DBG_CONFIG, 494 ath_print(common, ATH_DBG_CONFIG,
@@ -694,6 +745,10 @@ void ath9k_ani_work(struct work_struct *work)
694 745
695 short_cal_interval = ATH_STA_SHORT_CALINTERVAL; 746 short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
696 747
748 /* Only calibrate if awake */
749 if (ah->power_mode != ATH9K_PM_AWAKE)
750 goto set_timer;
751
697 /* Long calibration runs independently of short calibration. */ 752 /* Long calibration runs independently of short calibration. */
698 if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) { 753 if ((timestamp - common->ani.longcal_timer) >= ATH_LONG_CALINTERVAL) {
699 longcal = true; 754 longcal = true;
@@ -728,6 +783,9 @@ void ath9k_ani_work(struct work_struct *work)
728 783
729 /* Skip all processing if there's nothing to do. */ 784 /* Skip all processing if there's nothing to do. */
730 if (longcal || shortcal || aniflag) { 785 if (longcal || shortcal || aniflag) {
786
787 ath9k_htc_ps_wakeup(priv);
788
731 /* Call ANI routine if necessary */ 789 /* Call ANI routine if necessary */
732 if (aniflag) 790 if (aniflag)
733 ath9k_hw_ani_monitor(ah, ah->curchan); 791 ath9k_hw_ani_monitor(ah, ah->curchan);
@@ -749,8 +807,11 @@ void ath9k_ani_work(struct work_struct *work)
749 ah->curchan->channelFlags, 807 ah->curchan->channelFlags,
750 common->ani.noise_floor); 808 common->ani.noise_floor);
751 } 809 }
810
811 ath9k_htc_ps_restore(priv);
752 } 812 }
753 813
814set_timer:
754 /* 815 /*
755 * Set timer interval based on previous results. 816 * Set timer interval based on previous results.
756 * The interval must be the shortest necessary to satisfy ANI, 817 * The interval must be the shortest necessary to satisfy ANI,
@@ -995,7 +1056,7 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
995{ 1056{
996 struct ieee80211_hdr *hdr; 1057 struct ieee80211_hdr *hdr;
997 struct ath9k_htc_priv *priv = hw->priv; 1058 struct ath9k_htc_priv *priv = hw->priv;
998 int padpos, padsize; 1059 int padpos, padsize, ret;
999 1060
1000 hdr = (struct ieee80211_hdr *) skb->data; 1061 hdr = (struct ieee80211_hdr *) skb->data;
1001 1062
@@ -1009,8 +1070,19 @@ static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1009 memmove(skb->data, skb->data + padsize, padpos); 1070 memmove(skb->data, skb->data + padsize, padpos);
1010 } 1071 }
1011 1072
1012 if (ath9k_htc_tx_start(priv, skb) != 0) { 1073 ret = ath9k_htc_tx_start(priv, skb);
1013 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT, "Tx failed"); 1074 if (ret != 0) {
1075 if (ret == -ENOMEM) {
1076 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
1077 "Stopping TX queues\n");
1078 ieee80211_stop_queues(hw);
1079 spin_lock_bh(&priv->tx_lock);
1080 priv->tx_queues_stop = true;
1081 spin_unlock_bh(&priv->tx_lock);
1082 } else {
1083 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
1084 "Tx failed");
1085 }
1014 goto fail_tx; 1086 goto fail_tx;
1015 } 1087 }
1016 1088
@@ -1075,6 +1147,12 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
1075 priv->op_flags &= ~OP_INVALID; 1147 priv->op_flags &= ~OP_INVALID;
1076 htc_start(priv->htc); 1148 htc_start(priv->htc);
1077 1149
1150 spin_lock_bh(&priv->tx_lock);
1151 priv->tx_queues_stop = false;
1152 spin_unlock_bh(&priv->tx_lock);
1153
1154 ieee80211_wake_queues(hw);
1155
1078mutex_unlock: 1156mutex_unlock:
1079 mutex_unlock(&priv->mutex); 1157 mutex_unlock(&priv->mutex);
1080 return ret; 1158 return ret;
@@ -1096,6 +1174,7 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
1096 return; 1174 return;
1097 } 1175 }
1098 1176
1177 ath9k_htc_ps_wakeup(priv);
1099 htc_stop(priv->htc); 1178 htc_stop(priv->htc);
1100 WMI_CMD(WMI_DISABLE_INTR_CMDID); 1179 WMI_CMD(WMI_DISABLE_INTR_CMDID);
1101 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID); 1180 WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
@@ -1103,8 +1182,10 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
1103 ath9k_hw_phy_disable(ah); 1182 ath9k_hw_phy_disable(ah);
1104 ath9k_hw_disable(ah); 1183 ath9k_hw_disable(ah);
1105 ath9k_hw_configpcipowersave(ah, 1, 1); 1184 ath9k_hw_configpcipowersave(ah, 1, 1);
1106 ath9k_hw_setpower(ah, ATH9K_PM_FULL_SLEEP); 1185 ath9k_htc_ps_restore(priv);
1186 ath9k_htc_setpower(priv, ATH9K_PM_FULL_SLEEP);
1107 1187
1188 cancel_work_sync(&priv->ps_work);
1108 cancel_delayed_work_sync(&priv->ath9k_ani_work); 1189 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1109 cancel_delayed_work_sync(&priv->ath9k_aggr_work); 1190 cancel_delayed_work_sync(&priv->ath9k_aggr_work);
1110 cancel_delayed_work_sync(&priv->ath9k_led_blink_work); 1191 cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
@@ -1145,6 +1226,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1145 goto out; 1226 goto out;
1146 } 1227 }
1147 1228
1229 ath9k_htc_ps_wakeup(priv);
1148 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif)); 1230 memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
1149 memcpy(&hvif.myaddr, vif->addr, ETH_ALEN); 1231 memcpy(&hvif.myaddr, vif->addr, ETH_ALEN);
1150 1232
@@ -1191,6 +1273,7 @@ static int ath9k_htc_add_interface(struct ieee80211_hw *hw,
1191 1273
1192 priv->vif = vif; 1274 priv->vif = vif;
1193out: 1275out:
1276 ath9k_htc_ps_restore(priv);
1194 mutex_unlock(&priv->mutex); 1277 mutex_unlock(&priv->mutex);
1195 return ret; 1278 return ret;
1196} 1279}
@@ -1259,6 +1342,16 @@ static int ath9k_htc_config(struct ieee80211_hw *hw, u32 changed)
1259 } 1342 }
1260 1343
1261 } 1344 }
1345 if (changed & IEEE80211_CONF_CHANGE_PS) {
1346 if (conf->flags & IEEE80211_CONF_PS) {
1347 ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
1348 priv->ps_enabled = true;
1349 } else {
1350 priv->ps_enabled = false;
1351 cancel_work_sync(&priv->ps_work);
1352 ath9k_htc_setpower(priv, ATH9K_PM_AWAKE);
1353 }
1354 }
1262 1355
1263 if (changed & IEEE80211_CONF_CHANGE_MONITOR) { 1356 if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
1264 if (conf->flags & IEEE80211_CONF_MONITOR) { 1357 if (conf->flags & IEEE80211_CONF_MONITOR) {
@@ -1295,16 +1388,18 @@ static void ath9k_htc_configure_filter(struct ieee80211_hw *hw,
1295 1388
1296 mutex_lock(&priv->mutex); 1389 mutex_lock(&priv->mutex);
1297 1390
1391 ath9k_htc_ps_wakeup(priv);
1298 changed_flags &= SUPPORTED_FILTERS; 1392 changed_flags &= SUPPORTED_FILTERS;
1299 *total_flags &= SUPPORTED_FILTERS; 1393 *total_flags &= SUPPORTED_FILTERS;
1300 1394
1301 priv->rxfilter = *total_flags; 1395 priv->rxfilter = *total_flags;
1302 rfilt = ath9k_cmn_calcrxfilter(hw, priv->ah, priv->rxfilter); 1396 rfilt = ath9k_htc_calcrxfilter(priv);
1303 ath9k_hw_setrxfilter(priv->ah, rfilt); 1397 ath9k_hw_setrxfilter(priv->ah, rfilt);
1304 1398
1305 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG, 1399 ath_print(ath9k_hw_common(priv->ah), ATH_DBG_CONFIG,
1306 "Set HW RX filter: 0x%x\n", rfilt); 1400 "Set HW RX filter: 0x%x\n", rfilt);
1307 1401
1402 ath9k_htc_ps_restore(priv);
1308 mutex_unlock(&priv->mutex); 1403 mutex_unlock(&priv->mutex);
1309} 1404}
1310 1405
@@ -1382,6 +1477,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
1382 1477
1383 mutex_lock(&priv->mutex); 1478 mutex_lock(&priv->mutex);
1384 ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n"); 1479 ath_print(common, ATH_DBG_CONFIG, "Set HW Key\n");
1480 ath9k_htc_ps_wakeup(priv);
1385 1481
1386 switch (cmd) { 1482 switch (cmd) {
1387 case SET_KEY: 1483 case SET_KEY:
@@ -1404,6 +1500,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw,
1404 ret = -EINVAL; 1500 ret = -EINVAL;
1405 } 1501 }
1406 1502
1503 ath9k_htc_ps_restore(priv);
1407 mutex_unlock(&priv->mutex); 1504 mutex_unlock(&priv->mutex);
1408 1505
1409 return ret; 1506 return ret;
@@ -1419,6 +1516,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1419 struct ath_common *common = ath9k_hw_common(ah); 1516 struct ath_common *common = ath9k_hw_common(ah);
1420 1517
1421 mutex_lock(&priv->mutex); 1518 mutex_lock(&priv->mutex);
1519 ath9k_htc_ps_wakeup(priv);
1422 1520
1423 if (changed & BSS_CHANGED_ASSOC) { 1521 if (changed & BSS_CHANGED_ASSOC) {
1424 common->curaid = bss_conf->assoc ? 1522 common->curaid = bss_conf->assoc ?
@@ -1431,6 +1529,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1431 ath_start_ani(priv); 1529 ath_start_ani(priv);
1432 } else { 1530 } else {
1433 priv->op_flags &= ~OP_ASSOCIATED; 1531 priv->op_flags &= ~OP_ASSOCIATED;
1532 cancel_work_sync(&priv->ps_work);
1434 cancel_delayed_work_sync(&priv->ath9k_ani_work); 1533 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1435 } 1534 }
1436 } 1535 }
@@ -1450,7 +1549,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1450 ((changed & BSS_CHANGED_BEACON_ENABLED) && 1549 ((changed & BSS_CHANGED_BEACON_ENABLED) &&
1451 bss_conf->enable_beacon)) { 1550 bss_conf->enable_beacon)) {
1452 priv->op_flags |= OP_ENABLE_BEACON; 1551 priv->op_flags |= OP_ENABLE_BEACON;
1453 ath9k_htc_beacon_config(priv, vif, bss_conf); 1552 ath9k_htc_beacon_config(priv, vif);
1454 } 1553 }
1455 1554
1456 if (changed & BSS_CHANGED_BEACON) 1555 if (changed & BSS_CHANGED_BEACON)
@@ -1459,7 +1558,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1459 if ((changed & BSS_CHANGED_BEACON_ENABLED) && 1558 if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
1460 !bss_conf->enable_beacon) { 1559 !bss_conf->enable_beacon) {
1461 priv->op_flags &= ~OP_ENABLE_BEACON; 1560 priv->op_flags &= ~OP_ENABLE_BEACON;
1462 ath9k_htc_beacon_config(priv, vif, bss_conf); 1561 ath9k_htc_beacon_config(priv, vif);
1463 } 1562 }
1464 1563
1465 if (changed & BSS_CHANGED_ERP_PREAMBLE) { 1564 if (changed & BSS_CHANGED_ERP_PREAMBLE) {
@@ -1490,6 +1589,7 @@ static void ath9k_htc_bss_info_changed(struct ieee80211_hw *hw,
1490 ath9k_hw_init_global_settings(ah); 1589 ath9k_hw_init_global_settings(ah);
1491 } 1590 }
1492 1591
1592 ath9k_htc_ps_restore(priv);
1493 mutex_unlock(&priv->mutex); 1593 mutex_unlock(&priv->mutex);
1494} 1594}
1495 1595
@@ -1518,9 +1618,11 @@ static void ath9k_htc_reset_tsf(struct ieee80211_hw *hw)
1518{ 1618{
1519 struct ath9k_htc_priv *priv = hw->priv; 1619 struct ath9k_htc_priv *priv = hw->priv;
1520 1620
1621 ath9k_htc_ps_wakeup(priv);
1521 mutex_lock(&priv->mutex); 1622 mutex_lock(&priv->mutex);
1522 ath9k_hw_reset_tsf(priv->ah); 1623 ath9k_hw_reset_tsf(priv->ah);
1523 mutex_unlock(&priv->mutex); 1624 mutex_unlock(&priv->mutex);
1625 ath9k_htc_ps_restore(priv);
1524} 1626}
1525 1627
1526static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, 1628static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
@@ -1569,6 +1671,7 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw)
1569 spin_lock_bh(&priv->beacon_lock); 1671 spin_lock_bh(&priv->beacon_lock);
1570 priv->op_flags |= OP_SCANNING; 1672 priv->op_flags |= OP_SCANNING;
1571 spin_unlock_bh(&priv->beacon_lock); 1673 spin_unlock_bh(&priv->beacon_lock);
1674 cancel_work_sync(&priv->ps_work);
1572 cancel_delayed_work_sync(&priv->ath9k_ani_work); 1675 cancel_delayed_work_sync(&priv->ath9k_ani_work);
1573 mutex_unlock(&priv->mutex); 1676 mutex_unlock(&priv->mutex);
1574} 1677}
@@ -1577,13 +1680,17 @@ static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw)
1577{ 1680{
1578 struct ath9k_htc_priv *priv = hw->priv; 1681 struct ath9k_htc_priv *priv = hw->priv;
1579 1682
1683 ath9k_htc_ps_wakeup(priv);
1580 mutex_lock(&priv->mutex); 1684 mutex_lock(&priv->mutex);
1581 spin_lock_bh(&priv->beacon_lock); 1685 spin_lock_bh(&priv->beacon_lock);
1582 priv->op_flags &= ~OP_SCANNING; 1686 priv->op_flags &= ~OP_SCANNING;
1583 spin_unlock_bh(&priv->beacon_lock); 1687 spin_unlock_bh(&priv->beacon_lock);
1584 priv->op_flags |= OP_FULL_RESET; 1688 priv->op_flags |= OP_FULL_RESET;
1689 if (priv->op_flags & OP_ASSOCIATED)
1690 ath9k_htc_beacon_config(priv, NULL);
1585 ath_start_ani(priv); 1691 ath_start_ani(priv);
1586 mutex_unlock(&priv->mutex); 1692 mutex_unlock(&priv->mutex);
1693 ath9k_htc_ps_restore(priv);
1587} 1694}
1588 1695
1589static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value) 1696static int ath9k_htc_set_rts_threshold(struct ieee80211_hw *hw, u32 value)