aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-02-22 15:10:22 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-22 15:10:22 -0500
commit5db5e44cdcdc5ee9cc821bd4d63445af0bb34bce (patch)
treeb5e5787a6d5c15e589d275c7434ebbf341257234 /drivers/net/wireless/ath/ath9k/main.c
parentdb62983a1e4b2af9e79c97af768f0c8b80bd93f0 (diff)
parent320d6c1b56de5f461c6062625b9664095f90ee95 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c124
1 files changed, 92 insertions, 32 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 4ed43b2b8df6..a71550049d84 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -15,6 +15,7 @@
15 */ 15 */
16 16
17#include <linux/nl80211.h> 17#include <linux/nl80211.h>
18#include <linux/delay.h>
18#include "ath9k.h" 19#include "ath9k.h"
19#include "btcoex.h" 20#include "btcoex.h"
20 21
@@ -53,6 +54,21 @@ static u8 parse_mpdudensity(u8 mpdudensity)
53 } 54 }
54} 55}
55 56
57static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
58{
59 bool pending = false;
60
61 spin_lock_bh(&txq->axq_lock);
62
63 if (txq->axq_depth || !list_empty(&txq->axq_acq))
64 pending = true;
65 else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
66 pending = !list_empty(&txq->txq_fifo_pending);
67
68 spin_unlock_bh(&txq->axq_lock);
69 return pending;
70}
71
56bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode) 72bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
57{ 73{
58 unsigned long flags; 74 unsigned long flags;
@@ -1117,12 +1133,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
1117 ath9k_btcoex_timer_resume(sc); 1133 ath9k_btcoex_timer_resume(sc);
1118 } 1134 }
1119 1135
1120 /* User has the option to provide pm-qos value as a module
1121 * parameter rather than using the default value of
1122 * 'ATH9K_PM_QOS_DEFAULT_VALUE'.
1123 */
1124 pm_qos_update_request(&sc->pm_qos_req, ath9k_pm_qos_value);
1125
1126 if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en) 1136 if (ah->caps.pcie_lcr_extsync_en && common->bus_ops->extn_synch_en)
1127 common->bus_ops->extn_synch_en(common); 1137 common->bus_ops->extn_synch_en(common);
1128 1138
@@ -1267,8 +1277,6 @@ static void ath9k_stop(struct ieee80211_hw *hw)
1267 1277
1268 sc->sc_flags |= SC_OP_INVALID; 1278 sc->sc_flags |= SC_OP_INVALID;
1269 1279
1270 pm_qos_update_request(&sc->pm_qos_req, PM_QOS_DEFAULT_VALUE);
1271
1272 mutex_unlock(&sc->mutex); 1280 mutex_unlock(&sc->mutex);
1273 1281
1274 ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n"); 1282 ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
@@ -1291,24 +1299,10 @@ static void ath9k_reclaim_beacon(struct ath_softc *sc,
1291{ 1299{
1292 struct ath_vif *avp = (void *)vif->drv_priv; 1300 struct ath_vif *avp = (void *)vif->drv_priv;
1293 1301
1294 /* Disable SWBA interrupt */ 1302 ath9k_set_beaconing_status(sc, false);
1295 sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
1296 ath9k_ps_wakeup(sc);
1297 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1298 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1299 tasklet_kill(&sc->bcon_tasklet);
1300 ath9k_ps_restore(sc);
1301
1302 ath_beacon_return(sc, avp); 1303 ath_beacon_return(sc, avp);
1304 ath9k_set_beaconing_status(sc, true);
1303 sc->sc_flags &= ~SC_OP_BEACONS; 1305 sc->sc_flags &= ~SC_OP_BEACONS;
1304
1305 if (sc->nbcnvifs > 0) {
1306 /* Re-enable beaconing */
1307 sc->sc_ah->imask |= ATH9K_INT_SWBA;
1308 ath9k_ps_wakeup(sc);
1309 ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
1310 ath9k_ps_restore(sc);
1311 }
1312} 1306}
1313 1307
1314static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif) 1308static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
@@ -1436,16 +1430,17 @@ static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
1436 1430
1437 if (ath9k_uses_beacons(vif->type)) { 1431 if (ath9k_uses_beacons(vif->type)) {
1438 int error; 1432 int error;
1439 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1440 /* This may fail because upper levels do not have beacons 1433 /* This may fail because upper levels do not have beacons
1441 * properly configured yet. That's OK, we assume it 1434 * properly configured yet. That's OK, we assume it
1442 * will be properly configured and then we will be notified 1435 * will be properly configured and then we will be notified
1443 * in the info_changed method and set up beacons properly 1436 * in the info_changed method and set up beacons properly
1444 * there. 1437 * there.
1445 */ 1438 */
1439 ath9k_set_beaconing_status(sc, false);
1446 error = ath_beacon_alloc(sc, vif); 1440 error = ath_beacon_alloc(sc, vif);
1447 if (!error) 1441 if (!error)
1448 ath_beacon_config(sc, vif); 1442 ath_beacon_config(sc, vif);
1443 ath9k_set_beaconing_status(sc, true);
1449 } 1444 }
1450} 1445}
1451 1446
@@ -1676,8 +1671,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1676 else 1671 else
1677 sc->sc_flags &= ~SC_OP_OFFCHANNEL; 1672 sc->sc_flags &= ~SC_OP_OFFCHANNEL;
1678 1673
1679 ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n", 1674 ath_dbg(common, ATH_DBG_CONFIG,
1680 curchan->center_freq); 1675 "Set channel: %d MHz type: %d\n",
1676 curchan->center_freq, conf->channel_type);
1681 1677
1682 ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos], 1678 ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
1683 curchan, conf->channel_type); 1679 curchan, conf->channel_type);
@@ -1723,6 +1719,8 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1723 } 1719 }
1724 1720
1725 if (changed & IEEE80211_CONF_CHANGE_POWER) { 1721 if (changed & IEEE80211_CONF_CHANGE_POWER) {
1722 ath_dbg(common, ATH_DBG_CONFIG,
1723 "Set power: %d\n", conf->power_level);
1726 sc->config.txpowlimit = 2 * conf->power_level; 1724 sc->config.txpowlimit = 2 * conf->power_level;
1727 ath9k_ps_wakeup(sc); 1725 ath9k_ps_wakeup(sc);
1728 ath9k_cmn_update_txpow(ah, sc->curtxpow, 1726 ath9k_cmn_update_txpow(ah, sc->curtxpow,
@@ -1886,6 +1884,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1886 u32 changed) 1884 u32 changed)
1887{ 1885{
1888 struct ath_softc *sc = hw->priv; 1886 struct ath_softc *sc = hw->priv;
1887 struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
1889 struct ath_hw *ah = sc->sc_ah; 1888 struct ath_hw *ah = sc->sc_ah;
1890 struct ath_common *common = ath9k_hw_common(ah); 1889 struct ath_common *common = ath9k_hw_common(ah);
1891 struct ath_vif *avp = (void *)vif->drv_priv; 1890 struct ath_vif *avp = (void *)vif->drv_priv;
@@ -1914,10 +1913,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1914 /* Enable transmission of beacons (AP, IBSS, MESH) */ 1913 /* Enable transmission of beacons (AP, IBSS, MESH) */
1915 if ((changed & BSS_CHANGED_BEACON) || 1914 if ((changed & BSS_CHANGED_BEACON) ||
1916 ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) { 1915 ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
1917 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 1916 ath9k_set_beaconing_status(sc, false);
1918 error = ath_beacon_alloc(sc, vif); 1917 error = ath_beacon_alloc(sc, vif);
1919 if (!error) 1918 if (!error)
1920 ath_beacon_config(sc, vif); 1919 ath_beacon_config(sc, vif);
1920 ath9k_set_beaconing_status(sc, true);
1921 } 1921 }
1922 1922
1923 if (changed & BSS_CHANGED_ERP_SLOT) { 1923 if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1940,21 +1940,26 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
1940 } 1940 }
1941 1941
1942 /* Disable transmission of beacons */ 1942 /* Disable transmission of beacons */
1943 if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) 1943 if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
1944 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 1944 !bss_conf->enable_beacon) {
1945 ath9k_set_beaconing_status(sc, false);
1946 avp->is_bslot_active = false;
1947 ath9k_set_beaconing_status(sc, true);
1948 }
1945 1949
1946 if (changed & BSS_CHANGED_BEACON_INT) { 1950 if (changed & BSS_CHANGED_BEACON_INT) {
1947 sc->beacon_interval = bss_conf->beacon_int; 1951 cur_conf->beacon_interval = bss_conf->beacon_int;
1948 /* 1952 /*
1949 * In case of AP mode, the HW TSF has to be reset 1953 * In case of AP mode, the HW TSF has to be reset
1950 * when the beacon interval changes. 1954 * when the beacon interval changes.
1951 */ 1955 */
1952 if (vif->type == NL80211_IFTYPE_AP) { 1956 if (vif->type == NL80211_IFTYPE_AP) {
1953 sc->sc_flags |= SC_OP_TSF_RESET; 1957 sc->sc_flags |= SC_OP_TSF_RESET;
1954 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq); 1958 ath9k_set_beaconing_status(sc, false);
1955 error = ath_beacon_alloc(sc, vif); 1959 error = ath_beacon_alloc(sc, vif);
1956 if (!error) 1960 if (!error)
1957 ath_beacon_config(sc, vif); 1961 ath_beacon_config(sc, vif);
1962 ath9k_set_beaconing_status(sc, true);
1958 } else { 1963 } else {
1959 ath_beacon_config(sc, vif); 1964 ath_beacon_config(sc, vif);
1960 } 1965 }
@@ -2122,6 +2127,60 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
2122 mutex_unlock(&sc->mutex); 2127 mutex_unlock(&sc->mutex);
2123} 2128}
2124 2129
2130static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
2131{
2132#define ATH_FLUSH_TIMEOUT 60 /* ms */
2133 struct ath_softc *sc = hw->priv;
2134 struct ath_txq *txq;
2135 struct ath_hw *ah = sc->sc_ah;
2136 struct ath_common *common = ath9k_hw_common(ah);
2137 int i, j, npend = 0;
2138
2139 mutex_lock(&sc->mutex);
2140
2141 cancel_delayed_work_sync(&sc->tx_complete_work);
2142
2143 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
2144 if (!ATH_TXQ_SETUP(sc, i))
2145 continue;
2146 txq = &sc->tx.txq[i];
2147
2148 if (!drop) {
2149 for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
2150 if (!ath9k_has_pending_frames(sc, txq))
2151 break;
2152 usleep_range(1000, 2000);
2153 }
2154 }
2155
2156 if (drop || ath9k_has_pending_frames(sc, txq)) {
2157 ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
2158 txq->axq_qnum);
2159 spin_lock_bh(&txq->axq_lock);
2160 txq->txq_flush_inprogress = true;
2161 spin_unlock_bh(&txq->axq_lock);
2162
2163 ath9k_ps_wakeup(sc);
2164 ath9k_hw_stoptxdma(ah, txq->axq_qnum);
2165 npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
2166 ath9k_ps_restore(sc);
2167 if (npend)
2168 break;
2169
2170 ath_draintxq(sc, txq, false);
2171 txq->txq_flush_inprogress = false;
2172 }
2173 }
2174
2175 if (npend) {
2176 ath_reset(sc, false);
2177 txq->txq_flush_inprogress = false;
2178 }
2179
2180 ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
2181 mutex_unlock(&sc->mutex);
2182}
2183
2125struct ieee80211_ops ath9k_ops = { 2184struct ieee80211_ops ath9k_ops = {
2126 .tx = ath9k_tx, 2185 .tx = ath9k_tx,
2127 .start = ath9k_start, 2186 .start = ath9k_start,
@@ -2143,4 +2202,5 @@ struct ieee80211_ops ath9k_ops = {
2143 .get_survey = ath9k_get_survey, 2202 .get_survey = ath9k_get_survey,
2144 .rfkill_poll = ath9k_rfkill_poll_state, 2203 .rfkill_poll = ath9k_rfkill_poll_state,
2145 .set_coverage_class = ath9k_set_coverage_class, 2204 .set_coverage_class = ath9k_set_coverage_class,
2205 .flush = ath9k_flush,
2146}; 2206};