diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-09-09 07:00:10 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-10-07 16:39:20 -0400 |
commit | 75d7839f4c4ca472bcf0b71f6f682957e19f777a (patch) | |
tree | 0eb02cbdeb44564545f8deae51bcb380be32900f /drivers/net/wireless/ath/ath9k/main.c | |
parent | 7a2f0f58c865be9217356528ab6cf73feb35cb07 (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.c | 215 |
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 63e1f183b470..9ac1ee0638f0 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 | */ | ||
1312 | static 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 | |||
1335 | static 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 | |||
1343 | static 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 | */ | ||
1352 | static 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 | */ | ||
1383 | static 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 | */ | ||
1418 | static 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 | |||
1437 | static 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 | */ | ||
2078 | static 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 | |||
1909 | static int ath9k_start(struct ieee80211_hw *hw) | 2096 | static 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 | ||
2024 | mutex_unlock: | 2211 | mutex_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 | */ | ||
2319 | static 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 | |||
2129 | static void ath9k_stop(struct ieee80211_hw *hw) | 2332 | static 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 |