aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/main.c
diff options
context:
space:
mode:
authorSujith <Sujith.Manoharan@atheros.com>2010-01-08 00:06:00 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-01-12 13:57:59 -0500
commit0fca65c1c0569d6a143e978b6f4974c519033e63 (patch)
tree60878fa99e7af727ab4bf880992adebb830d21a5 /drivers/net/wireless/ath/ath9k/main.c
parentcc5d8a3772ee4e2ed29558ba548b4747959ba971 (diff)
ath9k: Add a new file for GPIO
Move all LED/RFKILL/BTCOEX related code to gpio.c Signed-off-by: Sujith <Sujith.Manoharan@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.c406
1 files changed, 0 insertions, 406 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 3777b8449789..31a33cf762da 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1000,174 +1000,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc,
1000 } 1000 }
1001} 1001}
1002 1002
1003/********************************/
1004/* LED functions */
1005/********************************/
1006
1007static void ath_led_blink_work(struct work_struct *work)
1008{
1009 struct ath_softc *sc = container_of(work, struct ath_softc,
1010 ath_led_blink_work.work);
1011
1012 if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
1013 return;
1014
1015 if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
1016 (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
1017 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
1018 else
1019 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
1020 (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
1021
1022 ieee80211_queue_delayed_work(sc->hw,
1023 &sc->ath_led_blink_work,
1024 (sc->sc_flags & SC_OP_LED_ON) ?
1025 msecs_to_jiffies(sc->led_off_duration) :
1026 msecs_to_jiffies(sc->led_on_duration));
1027
1028 sc->led_on_duration = sc->led_on_cnt ?
1029 max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
1030 ATH_LED_ON_DURATION_IDLE;
1031 sc->led_off_duration = sc->led_off_cnt ?
1032 max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
1033 ATH_LED_OFF_DURATION_IDLE;
1034 sc->led_on_cnt = sc->led_off_cnt = 0;
1035 if (sc->sc_flags & SC_OP_LED_ON)
1036 sc->sc_flags &= ~SC_OP_LED_ON;
1037 else
1038 sc->sc_flags |= SC_OP_LED_ON;
1039}
1040
1041static void ath_led_brightness(struct led_classdev *led_cdev,
1042 enum led_brightness brightness)
1043{
1044 struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
1045 struct ath_softc *sc = led->sc;
1046
1047 switch (brightness) {
1048 case LED_OFF:
1049 if (led->led_type == ATH_LED_ASSOC ||
1050 led->led_type == ATH_LED_RADIO) {
1051 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
1052 (led->led_type == ATH_LED_RADIO));
1053 sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
1054 if (led->led_type == ATH_LED_RADIO)
1055 sc->sc_flags &= ~SC_OP_LED_ON;
1056 } else {
1057 sc->led_off_cnt++;
1058 }
1059 break;
1060 case LED_FULL:
1061 if (led->led_type == ATH_LED_ASSOC) {
1062 sc->sc_flags |= SC_OP_LED_ASSOCIATED;
1063 ieee80211_queue_delayed_work(sc->hw,
1064 &sc->ath_led_blink_work, 0);
1065 } else if (led->led_type == ATH_LED_RADIO) {
1066 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
1067 sc->sc_flags |= SC_OP_LED_ON;
1068 } else {
1069 sc->led_on_cnt++;
1070 }
1071 break;
1072 default:
1073 break;
1074 }
1075}
1076
1077static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
1078 char *trigger)
1079{
1080 int ret;
1081
1082 led->sc = sc;
1083 led->led_cdev.name = led->name;
1084 led->led_cdev.default_trigger = trigger;
1085 led->led_cdev.brightness_set = ath_led_brightness;
1086
1087 ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
1088 if (ret)
1089 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
1090 "Failed to register led:%s", led->name);
1091 else
1092 led->registered = 1;
1093 return ret;
1094}
1095
1096static void ath_unregister_led(struct ath_led *led)
1097{
1098 if (led->registered) {
1099 led_classdev_unregister(&led->led_cdev);
1100 led->registered = 0;
1101 }
1102}
1103
1104static void ath_deinit_leds(struct ath_softc *sc)
1105{
1106 ath_unregister_led(&sc->assoc_led);
1107 sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
1108 ath_unregister_led(&sc->tx_led);
1109 ath_unregister_led(&sc->rx_led);
1110 ath_unregister_led(&sc->radio_led);
1111 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
1112}
1113
1114static void ath_init_leds(struct ath_softc *sc)
1115{
1116 char *trigger;
1117 int ret;
1118
1119 if (AR_SREV_9287(sc->sc_ah))
1120 sc->sc_ah->led_pin = ATH_LED_PIN_9287;
1121 else
1122 sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
1123
1124 /* Configure gpio 1 for output */
1125 ath9k_hw_cfg_output(sc->sc_ah, sc->sc_ah->led_pin,
1126 AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
1127 /* LED off, active low */
1128 ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
1129
1130 INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
1131
1132 trigger = ieee80211_get_radio_led_name(sc->hw);
1133 snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
1134 "ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
1135 ret = ath_register_led(sc, &sc->radio_led, trigger);
1136 sc->radio_led.led_type = ATH_LED_RADIO;
1137 if (ret)
1138 goto fail;
1139
1140 trigger = ieee80211_get_assoc_led_name(sc->hw);
1141 snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
1142 "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
1143 ret = ath_register_led(sc, &sc->assoc_led, trigger);
1144 sc->assoc_led.led_type = ATH_LED_ASSOC;
1145 if (ret)
1146 goto fail;
1147
1148 trigger = ieee80211_get_tx_led_name(sc->hw);
1149 snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
1150 "ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
1151 ret = ath_register_led(sc, &sc->tx_led, trigger);
1152 sc->tx_led.led_type = ATH_LED_TX;
1153 if (ret)
1154 goto fail;
1155
1156 trigger = ieee80211_get_rx_led_name(sc->hw);
1157 snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
1158 "ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
1159 ret = ath_register_led(sc, &sc->rx_led, trigger);
1160 sc->rx_led.led_type = ATH_LED_RX;
1161 if (ret)
1162 goto fail;
1163
1164 return;
1165
1166fail:
1167 cancel_delayed_work_sync(&sc->ath_led_blink_work);
1168 ath_deinit_leds(sc);
1169}
1170
1171void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) 1003void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
1172{ 1004{
1173 struct ath_hw *ah = sc->sc_ah; 1005 struct ath_hw *ah = sc->sc_ah;
@@ -1252,35 +1084,6 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
1252 ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); 1084 ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP);
1253} 1085}
1254 1086
1255/*******************/
1256/* Rfkill */
1257/*******************/
1258
1259static bool ath_is_rfkill_set(struct ath_softc *sc)
1260{
1261 struct ath_hw *ah = sc->sc_ah;
1262
1263 return ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
1264 ah->rfkill_polarity;
1265}
1266
1267static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
1268{
1269 struct ath_wiphy *aphy = hw->priv;
1270 struct ath_softc *sc = aphy->sc;
1271 bool blocked = !!ath_is_rfkill_set(sc);
1272
1273 wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
1274}
1275
1276static void ath_start_rfkill_poll(struct ath_softc *sc)
1277{
1278 struct ath_hw *ah = sc->sc_ah;
1279
1280 if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
1281 wiphy_rfkill_start_polling(sc->hw->wiphy);
1282}
1283
1284static void ath9k_uninit_hw(struct ath_softc *sc) 1087static void ath9k_uninit_hw(struct ath_softc *sc)
1285{ 1088{
1286 struct ath_hw *ah = sc->sc_ah; 1089 struct ath_hw *ah = sc->sc_ah;
@@ -1365,177 +1168,6 @@ static int ath9k_reg_notifier(struct wiphy *wiphy,
1365} 1168}
1366 1169
1367/* 1170/*
1368 * Detects if there is any priority bt traffic
1369 */
1370static void ath_detect_bt_priority(struct ath_softc *sc)
1371{
1372 struct ath_btcoex *btcoex = &sc->btcoex;
1373 struct ath_hw *ah = sc->sc_ah;
1374
1375 if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio))
1376 btcoex->bt_priority_cnt++;
1377
1378 if (time_after(jiffies, btcoex->bt_priority_time +
1379 msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
1380 if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
1381 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_BTCOEX,
1382 "BT priority traffic detected");
1383 sc->sc_flags |= SC_OP_BT_PRIORITY_DETECTED;
1384 } else {
1385 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
1386 }
1387
1388 btcoex->bt_priority_cnt = 0;
1389 btcoex->bt_priority_time = jiffies;
1390 }
1391}
1392
1393/*
1394 * Configures appropriate weight based on stomp type.
1395 */
1396static void ath9k_btcoex_bt_stomp(struct ath_softc *sc,
1397 enum ath_stomp_type stomp_type)
1398{
1399 struct ath_hw *ah = sc->sc_ah;
1400
1401 switch (stomp_type) {
1402 case ATH_BTCOEX_STOMP_ALL:
1403 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
1404 AR_STOMP_ALL_WLAN_WGHT);
1405 break;
1406 case ATH_BTCOEX_STOMP_LOW:
1407 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
1408 AR_STOMP_LOW_WLAN_WGHT);
1409 break;
1410 case ATH_BTCOEX_STOMP_NONE:
1411 ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
1412 AR_STOMP_NONE_WLAN_WGHT);
1413 break;
1414 default:
1415 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
1416 "Invalid Stomptype\n");
1417 break;
1418 }
1419
1420 ath9k_hw_btcoex_enable(ah);
1421}
1422
1423static void ath9k_gen_timer_start(struct ath_hw *ah,
1424 struct ath_gen_timer *timer,
1425 u32 timer_next,
1426 u32 timer_period)
1427{
1428 struct ath_common *common = ath9k_hw_common(ah);
1429 struct ath_softc *sc = (struct ath_softc *) common->priv;
1430
1431 ath9k_hw_gen_timer_start(ah, timer, timer_next, timer_period);
1432
1433 if ((sc->imask & ATH9K_INT_GENTIMER) == 0) {
1434 ath9k_hw_set_interrupts(ah, 0);
1435 sc->imask |= ATH9K_INT_GENTIMER;
1436 ath9k_hw_set_interrupts(ah, sc->imask);
1437 }
1438}
1439
1440static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
1441{
1442 struct ath_common *common = ath9k_hw_common(ah);
1443 struct ath_softc *sc = (struct ath_softc *) common->priv;
1444 struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers;
1445
1446 ath9k_hw_gen_timer_stop(ah, timer);
1447
1448 /* if no timer is enabled, turn off interrupt mask */
1449 if (timer_table->timer_mask.val == 0) {
1450 ath9k_hw_set_interrupts(ah, 0);
1451 sc->imask &= ~ATH9K_INT_GENTIMER;
1452 ath9k_hw_set_interrupts(ah, sc->imask);
1453 }
1454}
1455
1456/*
1457 * This is the master bt coex timer which runs for every
1458 * 45ms, bt traffic will be given priority during 55% of this
1459 * period while wlan gets remaining 45%
1460 */
1461static void ath_btcoex_period_timer(unsigned long data)
1462{
1463 struct ath_softc *sc = (struct ath_softc *) data;
1464 struct ath_hw *ah = sc->sc_ah;
1465 struct ath_btcoex *btcoex = &sc->btcoex;
1466
1467 ath_detect_bt_priority(sc);
1468
1469 spin_lock_bh(&btcoex->btcoex_lock);
1470
1471 ath9k_btcoex_bt_stomp(sc, btcoex->bt_stomp_type);
1472
1473 spin_unlock_bh(&btcoex->btcoex_lock);
1474
1475 if (btcoex->btcoex_period != btcoex->btcoex_no_stomp) {
1476 if (btcoex->hw_timer_enabled)
1477 ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
1478
1479 ath9k_gen_timer_start(ah,
1480 btcoex->no_stomp_timer,
1481 (ath9k_hw_gettsf32(ah) +
1482 btcoex->btcoex_no_stomp),
1483 btcoex->btcoex_no_stomp * 10);
1484 btcoex->hw_timer_enabled = true;
1485 }
1486
1487 mod_timer(&btcoex->period_timer, jiffies +
1488 msecs_to_jiffies(ATH_BTCOEX_DEF_BT_PERIOD));
1489}
1490
1491/*
1492 * Generic tsf based hw timer which configures weight
1493 * registers to time slice between wlan and bt traffic
1494 */
1495static void ath_btcoex_no_stomp_timer(void *arg)
1496{
1497 struct ath_softc *sc = (struct ath_softc *)arg;
1498 struct ath_hw *ah = sc->sc_ah;
1499 struct ath_btcoex *btcoex = &sc->btcoex;
1500
1501 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
1502 "no stomp timer running \n");
1503
1504 spin_lock_bh(&btcoex->btcoex_lock);
1505
1506 if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW)
1507 ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_NONE);
1508 else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
1509 ath9k_btcoex_bt_stomp(sc, ATH_BTCOEX_STOMP_LOW);
1510
1511 spin_unlock_bh(&btcoex->btcoex_lock);
1512}
1513
1514static int ath_init_btcoex_timer(struct ath_softc *sc)
1515{
1516 struct ath_btcoex *btcoex = &sc->btcoex;
1517
1518 btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;
1519 btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
1520 btcoex->btcoex_period / 100;
1521
1522 setup_timer(&btcoex->period_timer, ath_btcoex_period_timer,
1523 (unsigned long) sc);
1524
1525 spin_lock_init(&btcoex->btcoex_lock);
1526
1527 btcoex->no_stomp_timer = ath_gen_timer_alloc(sc->sc_ah,
1528 ath_btcoex_no_stomp_timer,
1529 ath_btcoex_no_stomp_timer,
1530 (void *) sc, AR_FIRST_NDP_TIMER);
1531
1532 if (!btcoex->no_stomp_timer)
1533 return -ENOMEM;
1534
1535 return 0;
1536}
1537
1538/*
1539 * Read and write, they both share the same lock. We do this to serialize 1171 * Read and write, they both share the same lock. We do this to serialize
1540 * reads and writes on Atheros 802.11n PCI devices only. This is required 1172 * reads and writes on Atheros 802.11n PCI devices only. This is required
1541 * as the FIFO on these devices can only accept sanely 2 requests. After 1173 * as the FIFO on these devices can only accept sanely 2 requests. After
@@ -2213,28 +1845,6 @@ void ath9k_update_ichannel(struct ath_softc *sc, struct ieee80211_hw *hw,
2213/* mac80211 callbacks */ 1845/* mac80211 callbacks */
2214/**********************/ 1846/**********************/
2215 1847
2216/*
2217 * (Re)start btcoex timers
2218 */
2219static void ath9k_btcoex_timer_resume(struct ath_softc *sc)
2220{
2221 struct ath_btcoex *btcoex = &sc->btcoex;
2222 struct ath_hw *ah = sc->sc_ah;
2223
2224 ath_print(ath9k_hw_common(ah), ATH_DBG_BTCOEX,
2225 "Starting btcoex timers");
2226
2227 /* make sure duty cycle timer is also stopped when resuming */
2228 if (btcoex->hw_timer_enabled)
2229 ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
2230
2231 btcoex->bt_priority_cnt = 0;
2232 btcoex->bt_priority_time = jiffies;
2233 sc->sc_flags &= ~SC_OP_BT_PRIORITY_DETECTED;
2234
2235 mod_timer(&btcoex->period_timer, jiffies);
2236}
2237
2238static int ath9k_start(struct ieee80211_hw *hw) 1848static int ath9k_start(struct ieee80211_hw *hw)
2239{ 1849{
2240 struct ath_wiphy *aphy = hw->priv; 1850 struct ath_wiphy *aphy = hw->priv;
@@ -2461,22 +2071,6 @@ exit:
2461 return 0; 2071 return 0;
2462} 2072}
2463 2073
2464/*
2465 * Pause btcoex timer and bt duty cycle timer
2466 */
2467static void ath9k_btcoex_timer_pause(struct ath_softc *sc)
2468{
2469 struct ath_btcoex *btcoex = &sc->btcoex;
2470 struct ath_hw *ah = sc->sc_ah;
2471
2472 del_timer_sync(&btcoex->period_timer);
2473
2474 if (btcoex->hw_timer_enabled)
2475 ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);
2476
2477 btcoex->hw_timer_enabled = false;
2478}
2479
2480static void ath9k_stop(struct ieee80211_hw *hw) 2074static void ath9k_stop(struct ieee80211_hw *hw)
2481{ 2075{
2482 struct ath_wiphy *aphy = hw->priv; 2076 struct ath_wiphy *aphy = hw->priv;