aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-09-09 07:00:10 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-10-07 16:39:20 -0400
commit75d7839f4c4ca472bcf0b71f6f682957e19f777a (patch)
tree0eb02cbdeb44564545f8deae51bcb380be32900f /drivers/net/wireless/ath/ath9k/main.c
parent7a2f0f58c865be9217356528ab6cf73feb35cb07 (diff)
ath9k: move driver core helpers to main.c
Keep on btcoex.c only hardware access helpers, move the driver core specific code to main.c. To accomplish this we had to split ath_init_btcoex_info() into two parts, the driver core part -- ath_init_btcoex_timer() and the hw specific part -- ath9k_hw_init_btcoex_hw_info(). This highlights how ath_gen_timer is part of the driver core, not hw related, so stuff that into ath_btcoex struct. The ath9k_hw_btcoex_init() code is now put inline on ath_init_softc() through a switch to it easier to follow, since we did that we can now call ath_tx_get_qnum() from the main.c instead of btcoex.c Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c215
1 files changed, 209 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 63e1f183b47..9ac1ee0638f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1286,9 +1286,9 @@ void ath_detach(struct ath_softc *sc)
1286 if (ATH_TXQ_SETUP(sc, i)) 1286 if (ATH_TXQ_SETUP(sc, i))
1287 ath_tx_cleanupq(sc, &sc->tx.txq[i]); 1287 ath_tx_cleanupq(sc, &sc->tx.txq[i]);
1288 1288
1289 if ((ah->btcoex_info.no_stomp_timer) && 1289 if ((sc->btcoex.no_stomp_timer) &&
1290 ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 1290 ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
1291 ath_gen_timer_free(ah, ah->btcoex_info.no_stomp_timer); 1291 ath_gen_timer_free(ah, sc->btcoex.no_stomp_timer);
1292 1292
1293 ath9k_hw_detach(ah); 1293 ath9k_hw_detach(ah);
1294 ath9k_exit_debug(ah); 1294 ath9k_exit_debug(ah);
@@ -1307,6 +1307,158 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
1307} 1307}
1308 1308
1309/* 1309/*
1310 * Detects if there is any priority bt traffic
1311 */
1312static void ath_detect_bt_priority(struct ath_softc *sc)
1313{
1314 struct ath_btcoex *btcoex = &sc->btcoex;
1315 struct ath_hw *ah = sc->sc_ah;
1316
1317 if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_info.btpriority_gpio))
1318 btcoex->bt_priority_cnt++;
1319
1320 if (time_after(jiffies, btcoex->bt_priority_time +
1321 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
1322 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
1323 DPRINTF(sc->sc_ah, ATH_DBG_BTCOEX,
1324 "BT priority traffic detected");
1325 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
1326 } else {
1327 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
1328 }
1329
1330 btcoex->bt_priority_cnt = 0;
1331 btcoex->bt_priority_time = jiffies;
1332 }
1333}
1334
1335static void ath_btcoex_set_weight(struct ath_btcoex_info *btcoex_info,
1336 u32 bt_weight,
1337 u32 wlan_weight)
1338{
1339 btcoex_info->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
1340 SM(wlan_weight, AR_BTCOEX_WL_WGHT);
1341}
1342
1343static void ath9k_hw_btcoex_init_weight(struct ath_hw *ah)
1344{
1345 ath_btcoex_set_weight(&ah->btcoex_info, AR_BT_COEX_WGHT,
1346 AR_STOMP_LOW_WLAN_WGHT);
1347}
1348
1349/*
1350 * Configures appropriate weight based on stomp type.
1351 */
1352static void ath_btcoex_bt_stomp(struct ath_softc *sc,
1353 struct ath_btcoex_info *btinfo,
1354 int stomp_type)
1355{
1356
1357 switch (stomp_type) {
1358 case ATH_BTCOEX_STOMP_ALL:
1359 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
1360 AR_STOMP_ALL_WLAN_WGHT);
1361 break;
1362 case ATH_BTCOEX_STOMP_LOW:
1363 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
1364 AR_STOMP_LOW_WLAN_WGHT);
1365 break;
1366 case ATH_BTCOEX_STOMP_NONE:
1367 ath_btcoex_set_weight(btinfo, AR_BT_COEX_WGHT,
1368 AR_STOMP_NONE_WLAN_WGHT);
1369 break;
1370 default:
1371 DPRINTF(sc->sc_ah, ATH_DBG_BTCOEX, "Invalid Stomptype\n");
1372 break;
1373 }
1374
1375 ath9k_hw_btcoex_enable(sc->sc_ah);
1376}
1377
1378/*
1379 * This is the master bt coex timer which runs for every
1380 * 45ms, bt traffic will be given priority during 55% of this
1381 * period while wlan gets remaining 45%
1382 */
1383static void ath_btcoex_period_timer(unsigned long data)
1384{
1385 struct ath_softc *sc = (struct ath_softc *) data;
1386 struct ath_hw *ah = sc->sc_ah;
1387 struct ath_btcoex *btcoex = &sc->btcoex;
1388 struct ath_btcoex_info *btinfo = &ah->btcoex_info;
1389
1390 ath_detect_bt_priority(sc);
1391
1392 spin_lock_bh(&btcoex->btcoex_lock);
1393
1394 ath_btcoex_bt_stomp(sc, btinfo, btinfo->bt_stomp_type);
1395
1396 spin_unlock_bh(&btcoex->btcoex_lock);
1397
1398 if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
1399 if (btcoex->hw_timer_enabled)
1400 ath_gen_timer_stop(ah, btcoex->no_stomp_timer);
1401
1402 ath_gen_timer_start(ah,
1403 btcoex->no_stomp_timer,
1404 (ath9k_hw_gettsf32(ah) +
1405 btcoex->btcoex_no_stomp),
1406 btcoex->btcoex_no_stomp * 10);
1407 btcoex->hw_timer_enabled = true;
1408 }
1409
1410 mod_timer(&btcoex->period_timer, jiffies +
1411 msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
1412}
1413
1414/*
1415 * Generic tsf based hw timer which configures weight
1416 * registers to time slice between wlan and bt traffic
1417 */
1418static void ath_btcoex_no_stomp_timer(void *arg)
1419{
1420 struct ath_softc *sc = (struct ath_softc *)arg;
1421 struct ath_hw *ah = sc->sc_ah;
1422 struct ath_btcoex *btcoex = &sc->btcoex;
1423 struct ath_btcoex_info *btinfo = &ah->btcoex_info;
1424
1425 DPRINTF(ah, ATH_DBG_BTCOEX, "no stomp timer running \n");
1426
1427 spin_lock_bh(&btcoex->btcoex_lock);
1428
1429 if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
1430 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_NONE);
1431 else if (btinfo->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
1432 ath_btcoex_bt_stomp(sc, btinfo, ATH_BTCOEX_STOMP_LOW);
1433
1434 spin_unlock_bh(&btcoex->btcoex_lock);
1435}
1436
1437static int ath_init_btcoex_timer(struct ath_softc *sc)
1438{
1439 struct ath_btcoex *btcoex = &sc->btcoex;
1440
1441 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
1442 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
1443 btcoex->btcoex_period / 100;
1444
1445 setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
1446 (unsigned long) sc);
1447
1448 spin_lock_init(&btcoex->btcoex_lock);
1449
1450 btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
1451 ath_btcoex_no_stomp_timer,
1452 ath_btcoex_no_stomp_timer,
1453 (void *) sc, AR_FIRST_NDP_TIMER);
1454
1455 if (!btcoex->no_stomp_timer)
1456 return -ENOMEM;
1457
1458 return 0;
1459}
1460
1461/*
1310 * Initialize and fill ath_softc, ath_sofct is the 1462 * Initialize and fill ath_softc, ath_sofct is the
1311 * "Software Carrier" struct. Historically it has existed 1463 * "Software Carrier" struct. Historically it has existed
1312 * to allow the separation between hardware specific 1464 * to allow the separation between hardware specific
@@ -1317,6 +1469,7 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid)
1317 struct ath_hw *ah = NULL; 1469 struct ath_hw *ah = NULL;
1318 int r = 0, i; 1470 int r = 0, i;
1319 int csz = 0; 1471 int csz = 0;
1472 int qnum;
1320 1473
1321 /* XXX: hardware will not be ready until ath_open() being called */ 1474 /* XXX: hardware will not be ready until ath_open() being called */
1322 sc->sc_flags |= SC_OP_INVALID; 1475 sc->sc_flags |= SC_OP_INVALID;
@@ -1521,10 +1674,23 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid)
1521 ARRAY_SIZE(ath9k_5ghz_chantable); 1674 ARRAY_SIZE(ath9k_5ghz_chantable);
1522 } 1675 }
1523 1676
1524 if (ah->btcoex_info.btcoex_scheme != ATH_BTCOEX_CFG_NONE) { 1677 switch (ah->btcoex_info.btcoex_scheme) {
1525 r = ath9k_hw_btcoex_init(ah); 1678 case ATH_BTCOEX_CFG_NONE:
1679 break;
1680 case ATH_BTCOEX_CFG_2WIRE:
1681 ath9k_hw_btcoex_init_2wire(ah);
1682 break;
1683 case ATH_BTCOEX_CFG_3WIRE:
1684 ath9k_hw_btcoex_init_3wire(ah);
1685 r = ath_init_btcoex_timer(sc);
1526 if (r) 1686 if (r)
1527 goto bad2; 1687 goto bad2;
1688 qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA, ATH9K_WME_AC_BE);
1689 ath9k_hw_init_btcoex_hw_info(ah, qnum);
1690 break;
1691 default:
1692 WARN_ON(1);
1693 break;
1528 } 1694 }
1529 1695
1530 return 0; 1696 return 0;
@@ -1906,6 +2072,27 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
1906/* mac80211 callbacks */ 2072/* mac80211 callbacks */
1907/**********************/ 2073/**********************/
1908 2074
2075/*
2076 * (Re)start btcoex timers
2077 */
2078static void ath9k_btcoex_timer_resume(struct ath_softc *sc)
2079{
2080 struct ath_btcoex *btcoex = &sc->btcoex;
2081 struct ath_hw *ah = sc->sc_ah;
2082
2083 DPRINTF(ah, ATH_DBG_BTCOEX, "Starting btcoex timers");
2084
2085 /* make sure duty cycle timer is also stopped when resuming */
2086 if (btcoex->hw_timer_enabled)
2087 ath_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
2088
2089 btcoex->bt_priority_cnt = 0;
2090 btcoex->bt_priority_time = jiffies;
2091 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
2092
2093 mod_timer(&btcoex->period_timer, jiffies);
2094}
2095
1909static int ath9k_start(struct ieee80211_hw *hw) 2096static int ath9k_start(struct ieee80211_hw *hw)
1910{ 2097{
1911 struct ath_wiphy *aphy = hw->priv; 2098 struct ath_wiphy *aphy = hw->priv;
@@ -2018,7 +2205,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
2018 2205
2019 ath_pcie_aspm_disable(sc); 2206 ath_pcie_aspm_disable(sc);
2020 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 2207 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
2021 ath_btcoex_timer_resume(sc); 2208 ath9k_btcoex_timer_resume(sc);
2022 } 2209 }
2023 2210
2024mutex_unlock: 2211mutex_unlock:
@@ -2126,6 +2313,22 @@ exit:
2126 return 0; 2313 return 0;
2127} 2314}
2128 2315
2316/*
2317 * Pause btcoex timer and bt duty cycle timer
2318 */
2319static void ath9k_btcoex_timer_pause(struct ath_softc *sc)
2320{
2321 struct ath_btcoex *btcoex = &sc->btcoex;
2322 struct ath_hw *ah = sc->sc_ah;
2323
2324 del_timer_sync(&btcoex->period_timer);
2325
2326 if (btcoex->hw_timer_enabled)
2327 ath_gen_timer_stop(ah, btcoex->no_stomp_timer);
2328
2329 btcoex->hw_timer_enabled = false;
2330}
2331
2129static void ath9k_stop(struct ieee80211_hw *hw) 2332static void ath9k_stop(struct ieee80211_hw *hw)
2130{ 2333{
2131 struct ath_wiphy *aphy = hw->priv; 2334 struct ath_wiphy *aphy = hw->priv;
@@ -2158,7 +2361,7 @@ static void ath9k_stop(struct ieee80211_hw *hw)
2158 if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) { 2361 if (sc->sc_flags & SC_OP_BTCOEX_ENABLED) {
2159 ath9k_hw_btcoex_disable(ah); 2362 ath9k_hw_btcoex_disable(ah);
2160 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE) 2363 if (ah->btcoex_info.btcoex_scheme == ATH_BTCOEX_CFG_3WIRE)
2161 ath_btcoex_timer_pause(sc); 2364 ath9k_btcoex_timer_pause(sc);
2162 } 2365 }
2163 2366
2164 /* make sure h/w will not generate any interrupt 2367 /* make sure h/w will not generate any interrupt