diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 130 |
1 files changed, 41 insertions, 89 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index f7baa406918b..9f49a3251d4d 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -231,6 +231,19 @@ static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band) | |||
231 | } | 231 | } |
232 | } | 232 | } |
233 | 233 | ||
234 | static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, | ||
235 | struct ieee80211_hw *hw) | ||
236 | { | ||
237 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
238 | struct ath9k_channel *channel; | ||
239 | u8 chan_idx; | ||
240 | |||
241 | chan_idx = curchan->hw_value; | ||
242 | channel = &sc->sc_ah->channels[chan_idx]; | ||
243 | ath9k_update_ichannel(sc, hw, channel); | ||
244 | return channel; | ||
245 | } | ||
246 | |||
234 | /* | 247 | /* |
235 | * Set/change channels. If the channel is really being changed, it's done | 248 | * Set/change channels. If the channel is really being changed, it's done |
236 | * by reseting the chip. To accomplish this we must first cleanup any pending | 249 | * by reseting the chip. To accomplish this we must first cleanup any pending |
@@ -283,7 +296,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
283 | "reset status %d\n", | 296 | "reset status %d\n", |
284 | channel->center_freq, r); | 297 | channel->center_freq, r); |
285 | spin_unlock_bh(&sc->sc_resetlock); | 298 | spin_unlock_bh(&sc->sc_resetlock); |
286 | return r; | 299 | goto ps_restore; |
287 | } | 300 | } |
288 | spin_unlock_bh(&sc->sc_resetlock); | 301 | spin_unlock_bh(&sc->sc_resetlock); |
289 | 302 | ||
@@ -292,14 +305,17 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
292 | if (ath_startrecv(sc) != 0) { | 305 | if (ath_startrecv(sc) != 0) { |
293 | DPRINTF(sc, ATH_DBG_FATAL, | 306 | DPRINTF(sc, ATH_DBG_FATAL, |
294 | "Unable to restart recv logic\n"); | 307 | "Unable to restart recv logic\n"); |
295 | return -EIO; | 308 | r = -EIO; |
309 | goto ps_restore; | ||
296 | } | 310 | } |
297 | 311 | ||
298 | ath_cache_conf_rate(sc, &hw->conf); | 312 | ath_cache_conf_rate(sc, &hw->conf); |
299 | ath_update_txpow(sc); | 313 | ath_update_txpow(sc); |
300 | ath9k_hw_set_interrupts(ah, sc->imask); | 314 | ath9k_hw_set_interrupts(ah, sc->imask); |
315 | |||
316 | ps_restore: | ||
301 | ath9k_ps_restore(sc); | 317 | ath9k_ps_restore(sc); |
302 | return 0; | 318 | return r; |
303 | } | 319 | } |
304 | 320 | ||
305 | /* | 321 | /* |
@@ -1110,6 +1126,9 @@ void ath_radio_enable(struct ath_softc *sc) | |||
1110 | ath9k_ps_wakeup(sc); | 1126 | ath9k_ps_wakeup(sc); |
1111 | ath9k_hw_configpcipowersave(ah, 0); | 1127 | ath9k_hw_configpcipowersave(ah, 0); |
1112 | 1128 | ||
1129 | if (!ah->curchan) | ||
1130 | ah->curchan = ath_get_curchannel(sc, sc->hw); | ||
1131 | |||
1113 | spin_lock_bh(&sc->sc_resetlock); | 1132 | spin_lock_bh(&sc->sc_resetlock); |
1114 | r = ath9k_hw_reset(ah, ah->curchan, false); | 1133 | r = ath9k_hw_reset(ah, ah->curchan, false); |
1115 | if (r) { | 1134 | if (r) { |
@@ -1162,6 +1181,9 @@ void ath_radio_disable(struct ath_softc *sc) | |||
1162 | ath_stoprecv(sc); /* turn off frame recv */ | 1181 | ath_stoprecv(sc); /* turn off frame recv */ |
1163 | ath_flushrecv(sc); /* flush recv queue */ | 1182 | ath_flushrecv(sc); /* flush recv queue */ |
1164 | 1183 | ||
1184 | if (!ah->curchan) | ||
1185 | ah->curchan = ath_get_curchannel(sc, sc->hw); | ||
1186 | |||
1165 | spin_lock_bh(&sc->sc_resetlock); | 1187 | spin_lock_bh(&sc->sc_resetlock); |
1166 | r = ath9k_hw_reset(ah, ah->curchan, false); | 1188 | r = ath9k_hw_reset(ah, ah->curchan, false); |
1167 | if (r) { | 1189 | if (r) { |
@@ -1178,8 +1200,6 @@ void ath_radio_disable(struct ath_softc *sc) | |||
1178 | ath9k_ps_restore(sc); | 1200 | ath9k_ps_restore(sc); |
1179 | } | 1201 | } |
1180 | 1202 | ||
1181 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
1182 | |||
1183 | /*******************/ | 1203 | /*******************/ |
1184 | /* Rfkill */ | 1204 | /* Rfkill */ |
1185 | /*******************/ | 1205 | /*******************/ |
@@ -1192,81 +1212,27 @@ static bool ath_is_rfkill_set(struct ath_softc *sc) | |||
1192 | ah->rfkill_polarity; | 1212 | ah->rfkill_polarity; |
1193 | } | 1213 | } |
1194 | 1214 | ||
1195 | /* s/w rfkill handlers */ | 1215 | static void ath9k_rfkill_poll_state(struct ieee80211_hw *hw) |
1196 | static int ath_rfkill_set_block(void *data, bool blocked) | ||
1197 | { | 1216 | { |
1198 | struct ath_softc *sc = data; | 1217 | struct ath_wiphy *aphy = hw->priv; |
1199 | 1218 | struct ath_softc *sc = aphy->sc; | |
1200 | if (blocked) | ||
1201 | ath_radio_disable(sc); | ||
1202 | else | ||
1203 | ath_radio_enable(sc); | ||
1204 | |||
1205 | return 0; | ||
1206 | } | ||
1207 | |||
1208 | static void ath_rfkill_poll_state(struct rfkill *rfkill, void *data) | ||
1209 | { | ||
1210 | struct ath_softc *sc = data; | ||
1211 | bool blocked = !!ath_is_rfkill_set(sc); | 1219 | bool blocked = !!ath_is_rfkill_set(sc); |
1212 | 1220 | ||
1213 | if (rfkill_set_hw_state(rfkill, blocked)) | 1221 | wiphy_rfkill_set_hw_state(hw->wiphy, blocked); |
1222 | |||
1223 | if (blocked) | ||
1214 | ath_radio_disable(sc); | 1224 | ath_radio_disable(sc); |
1215 | else | 1225 | else |
1216 | ath_radio_enable(sc); | 1226 | ath_radio_enable(sc); |
1217 | } | 1227 | } |
1218 | 1228 | ||
1219 | /* Init s/w rfkill */ | 1229 | static void ath_start_rfkill_poll(struct ath_softc *sc) |
1220 | static int ath_init_sw_rfkill(struct ath_softc *sc) | ||
1221 | { | ||
1222 | sc->rf_kill.ops.set_block = ath_rfkill_set_block; | ||
1223 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) | ||
1224 | sc->rf_kill.ops.poll = ath_rfkill_poll_state; | ||
1225 | |||
1226 | snprintf(sc->rf_kill.rfkill_name, sizeof(sc->rf_kill.rfkill_name), | ||
1227 | "ath9k-%s::rfkill", wiphy_name(sc->hw->wiphy)); | ||
1228 | |||
1229 | sc->rf_kill.rfkill = rfkill_alloc(sc->rf_kill.rfkill_name, | ||
1230 | wiphy_dev(sc->hw->wiphy), | ||
1231 | RFKILL_TYPE_WLAN, | ||
1232 | &sc->rf_kill.ops, sc); | ||
1233 | if (!sc->rf_kill.rfkill) { | ||
1234 | DPRINTF(sc, ATH_DBG_FATAL, "Failed to allocate rfkill\n"); | ||
1235 | return -ENOMEM; | ||
1236 | } | ||
1237 | |||
1238 | return 0; | ||
1239 | } | ||
1240 | |||
1241 | /* Deinitialize rfkill */ | ||
1242 | static void ath_deinit_rfkill(struct ath_softc *sc) | ||
1243 | { | ||
1244 | if (sc->sc_flags & SC_OP_RFKILL_REGISTERED) { | ||
1245 | rfkill_unregister(sc->rf_kill.rfkill); | ||
1246 | rfkill_destroy(sc->rf_kill.rfkill); | ||
1247 | sc->sc_flags &= ~SC_OP_RFKILL_REGISTERED; | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1251 | static int ath_start_rfkill_poll(struct ath_softc *sc) | ||
1252 | { | 1230 | { |
1253 | if (!(sc->sc_flags & SC_OP_RFKILL_REGISTERED)) { | 1231 | struct ath_hw *ah = sc->sc_ah; |
1254 | if (rfkill_register(sc->rf_kill.rfkill)) { | ||
1255 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1256 | "Unable to register rfkill\n"); | ||
1257 | rfkill_destroy(sc->rf_kill.rfkill); | ||
1258 | |||
1259 | /* Deinitialize the device */ | ||
1260 | ath_cleanup(sc); | ||
1261 | return -EIO; | ||
1262 | } else { | ||
1263 | sc->sc_flags |= SC_OP_RFKILL_REGISTERED; | ||
1264 | } | ||
1265 | } | ||
1266 | 1232 | ||
1267 | return 0; | 1233 | if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT) |
1234 | wiphy_rfkill_start_polling(sc->hw->wiphy); | ||
1268 | } | 1235 | } |
1269 | #endif /* CONFIG_RFKILL */ | ||
1270 | 1236 | ||
1271 | void ath_cleanup(struct ath_softc *sc) | 1237 | void ath_cleanup(struct ath_softc *sc) |
1272 | { | 1238 | { |
@@ -1286,9 +1252,6 @@ void ath_detach(struct ath_softc *sc) | |||
1286 | 1252 | ||
1287 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); | 1253 | DPRINTF(sc, ATH_DBG_CONFIG, "Detach ATH hw\n"); |
1288 | 1254 | ||
1289 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
1290 | ath_deinit_rfkill(sc); | ||
1291 | #endif | ||
1292 | ath_deinit_leds(sc); | 1255 | ath_deinit_leds(sc); |
1293 | cancel_work_sync(&sc->chan_work); | 1256 | cancel_work_sync(&sc->chan_work); |
1294 | cancel_delayed_work_sync(&sc->wiphy_work); | 1257 | cancel_delayed_work_sync(&sc->wiphy_work); |
@@ -1626,13 +1589,6 @@ int ath_attach(u16 devid, struct ath_softc *sc) | |||
1626 | if (error != 0) | 1589 | if (error != 0) |
1627 | goto error_attach; | 1590 | goto error_attach; |
1628 | 1591 | ||
1629 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
1630 | /* Initialize s/w rfkill */ | ||
1631 | error = ath_init_sw_rfkill(sc); | ||
1632 | if (error) | ||
1633 | goto error_attach; | ||
1634 | #endif | ||
1635 | |||
1636 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); | 1592 | INIT_WORK(&sc->chan_work, ath9k_wiphy_chan_work); |
1637 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); | 1593 | INIT_DELAYED_WORK(&sc->wiphy_work, ath9k_wiphy_work); |
1638 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); | 1594 | sc->wiphy_scheduler_int = msecs_to_jiffies(500); |
@@ -1648,6 +1604,7 @@ int ath_attach(u16 devid, struct ath_softc *sc) | |||
1648 | /* Initialize LED control */ | 1604 | /* Initialize LED control */ |
1649 | ath_init_leds(sc); | 1605 | ath_init_leds(sc); |
1650 | 1606 | ||
1607 | ath_start_rfkill_poll(sc); | ||
1651 | 1608 | ||
1652 | return 0; | 1609 | return 0; |
1653 | 1610 | ||
@@ -1920,7 +1877,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1920 | struct ath_softc *sc = aphy->sc; | 1877 | struct ath_softc *sc = aphy->sc; |
1921 | struct ieee80211_channel *curchan = hw->conf.channel; | 1878 | struct ieee80211_channel *curchan = hw->conf.channel; |
1922 | struct ath9k_channel *init_channel; | 1879 | struct ath9k_channel *init_channel; |
1923 | int r, pos; | 1880 | int r; |
1924 | 1881 | ||
1925 | DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " | 1882 | DPRINTF(sc, ATH_DBG_CONFIG, "Starting driver with " |
1926 | "initial channel: %d MHz\n", curchan->center_freq); | 1883 | "initial channel: %d MHz\n", curchan->center_freq); |
@@ -1950,11 +1907,9 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1950 | 1907 | ||
1951 | /* setup initial channel */ | 1908 | /* setup initial channel */ |
1952 | 1909 | ||
1953 | pos = curchan->hw_value; | 1910 | sc->chan_idx = curchan->hw_value; |
1954 | 1911 | ||
1955 | sc->chan_idx = pos; | 1912 | init_channel = ath_get_curchannel(sc, hw); |
1956 | init_channel = &sc->sc_ah->channels[pos]; | ||
1957 | ath9k_update_ichannel(sc, hw, init_channel); | ||
1958 | 1913 | ||
1959 | /* Reset SERDES registers */ | 1914 | /* Reset SERDES registers */ |
1960 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); | 1915 | ath9k_hw_configpcipowersave(sc->sc_ah, 0); |
@@ -2018,10 +1973,6 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
2018 | 1973 | ||
2019 | ieee80211_wake_queues(hw); | 1974 | ieee80211_wake_queues(hw); |
2020 | 1975 | ||
2021 | #if defined(CONFIG_RFKILL) || defined(CONFIG_RFKILL_MODULE) | ||
2022 | r = ath_start_rfkill_poll(sc); | ||
2023 | #endif | ||
2024 | |||
2025 | mutex_unlock: | 1976 | mutex_unlock: |
2026 | mutex_unlock(&sc->mutex); | 1977 | mutex_unlock(&sc->mutex); |
2027 | 1978 | ||
@@ -2159,7 +2110,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
2159 | } else | 2110 | } else |
2160 | sc->rx.rxlink = NULL; | 2111 | sc->rx.rxlink = NULL; |
2161 | 2112 | ||
2162 | rfkill_pause_polling(sc->rf_kill.rfkill); | 2113 | wiphy_rfkill_stop_polling(sc->hw->wiphy); |
2163 | 2114 | ||
2164 | /* disable HAL and put h/w to sleep */ | 2115 | /* disable HAL and put h/w to sleep */ |
2165 | ath9k_hw_disable(sc->sc_ah); | 2116 | ath9k_hw_disable(sc->sc_ah); |
@@ -2765,6 +2716,7 @@ struct ieee80211_ops ath9k_ops = { | |||
2765 | .ampdu_action = ath9k_ampdu_action, | 2716 | .ampdu_action = ath9k_ampdu_action, |
2766 | .sw_scan_start = ath9k_sw_scan_start, | 2717 | .sw_scan_start = ath9k_sw_scan_start, |
2767 | .sw_scan_complete = ath9k_sw_scan_complete, | 2718 | .sw_scan_complete = ath9k_sw_scan_complete, |
2719 | .rfkill_poll = ath9k_rfkill_poll_state, | ||
2768 | }; | 2720 | }; |
2769 | 2721 | ||
2770 | static struct { | 2722 | static struct { |