diff options
author | Ben Greear <greearb@candelatech.com> | 2014-05-16 10:15:38 -0400 |
---|---|---|
committer | Kalle Valo <kvalo@qca.qualcomm.com> | 2014-05-22 12:55:09 -0400 |
commit | 46acf7bb9b61289ea3353561142e3bf41119bd3e (patch) | |
tree | 1201b3c0c3081e33f79a8e342e00729a40de26f7 /drivers/net/wireless | |
parent | eeab266c0f3c9c85ef649ba737e2d553742a2532 (diff) |
ath10k: support get/set antenna configurations.
Verified that target's tx/rx chain register is set appropriately,
and that the tx rate goes down as number of chains
decrease, but I did not actually try to verify antenna
ceased to transmit when disabled.
kvalo: move ar->supp_*_chainmask initialisation to ath10k_mac_register()
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Avery Pennarun <apenwarr@gmail.com>
Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 6 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 80 |
2 files changed, 86 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 2c1dfd719146..679b2a32331b 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -440,6 +440,12 @@ struct ath10k { | |||
440 | bool radar_enabled; | 440 | bool radar_enabled; |
441 | int num_started_vdevs; | 441 | int num_started_vdevs; |
442 | 442 | ||
443 | /* Protected by conf-mutex */ | ||
444 | u8 supp_tx_chainmask; | ||
445 | u8 supp_rx_chainmask; | ||
446 | u8 cfg_tx_chainmask; | ||
447 | u8 cfg_rx_chainmask; | ||
448 | |||
443 | struct wmi_pdev_set_wmm_params_arg wmm_params; | 449 | struct wmi_pdev_set_wmm_params_arg wmm_params; |
444 | struct completion install_key_done; | 450 | struct completion install_key_done; |
445 | 451 | ||
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 12518047bd31..8c997626f45f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -2332,6 +2332,68 @@ void ath10k_halt(struct ath10k *ar) | |||
2332 | spin_unlock_bh(&ar->data_lock); | 2332 | spin_unlock_bh(&ar->data_lock); |
2333 | } | 2333 | } |
2334 | 2334 | ||
2335 | static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | ||
2336 | { | ||
2337 | struct ath10k *ar = hw->priv; | ||
2338 | |||
2339 | mutex_lock(&ar->conf_mutex); | ||
2340 | |||
2341 | if (ar->cfg_tx_chainmask) { | ||
2342 | *tx_ant = ar->cfg_tx_chainmask; | ||
2343 | *rx_ant = ar->cfg_rx_chainmask; | ||
2344 | } else { | ||
2345 | *tx_ant = ar->supp_tx_chainmask; | ||
2346 | *rx_ant = ar->supp_rx_chainmask; | ||
2347 | } | ||
2348 | |||
2349 | mutex_unlock(&ar->conf_mutex); | ||
2350 | |||
2351 | return 0; | ||
2352 | } | ||
2353 | |||
2354 | static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant) | ||
2355 | { | ||
2356 | int ret; | ||
2357 | |||
2358 | lockdep_assert_held(&ar->conf_mutex); | ||
2359 | |||
2360 | ar->cfg_tx_chainmask = tx_ant; | ||
2361 | ar->cfg_rx_chainmask = rx_ant; | ||
2362 | |||
2363 | if ((ar->state != ATH10K_STATE_ON) && | ||
2364 | (ar->state != ATH10K_STATE_RESTARTED)) | ||
2365 | return 0; | ||
2366 | |||
2367 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_chain_mask, | ||
2368 | tx_ant); | ||
2369 | if (ret) { | ||
2370 | ath10k_warn("failed to set tx-chainmask: %d, req 0x%x\n", | ||
2371 | ret, tx_ant); | ||
2372 | return ret; | ||
2373 | } | ||
2374 | |||
2375 | ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rx_chain_mask, | ||
2376 | rx_ant); | ||
2377 | if (ret) { | ||
2378 | ath10k_warn("failed to set rx-chainmask: %d, req 0x%x\n", | ||
2379 | ret, rx_ant); | ||
2380 | return ret; | ||
2381 | } | ||
2382 | |||
2383 | return 0; | ||
2384 | } | ||
2385 | |||
2386 | static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant) | ||
2387 | { | ||
2388 | struct ath10k *ar = hw->priv; | ||
2389 | int ret; | ||
2390 | |||
2391 | mutex_lock(&ar->conf_mutex); | ||
2392 | ret = __ath10k_set_antenna(ar, tx_ant, rx_ant); | ||
2393 | mutex_unlock(&ar->conf_mutex); | ||
2394 | return ret; | ||
2395 | } | ||
2396 | |||
2335 | static int ath10k_start(struct ieee80211_hw *hw) | 2397 | static int ath10k_start(struct ieee80211_hw *hw) |
2336 | { | 2398 | { |
2337 | struct ath10k *ar = hw->priv; | 2399 | struct ath10k *ar = hw->priv; |
@@ -2373,6 +2435,10 @@ static int ath10k_start(struct ieee80211_hw *hw) | |||
2373 | if (ret) | 2435 | if (ret) |
2374 | ath10k_warn("failed to enable dynamic BW: %d\n", ret); | 2436 | ath10k_warn("failed to enable dynamic BW: %d\n", ret); |
2375 | 2437 | ||
2438 | if (ar->cfg_tx_chainmask) | ||
2439 | __ath10k_set_antenna(ar, ar->cfg_tx_chainmask, | ||
2440 | ar->cfg_rx_chainmask); | ||
2441 | |||
2376 | /* | 2442 | /* |
2377 | * By default FW set ARP frames ac to voice (6). In that case ARP | 2443 | * By default FW set ARP frames ac to voice (6). In that case ARP |
2378 | * exchange is not working properly for UAPSD enabled AP. ARP requests | 2444 | * exchange is not working properly for UAPSD enabled AP. ARP requests |
@@ -4256,6 +4322,8 @@ static const struct ieee80211_ops ath10k_ops = { | |||
4256 | .set_frag_threshold = ath10k_set_frag_threshold, | 4322 | .set_frag_threshold = ath10k_set_frag_threshold, |
4257 | .flush = ath10k_flush, | 4323 | .flush = ath10k_flush, |
4258 | .tx_last_beacon = ath10k_tx_last_beacon, | 4324 | .tx_last_beacon = ath10k_tx_last_beacon, |
4325 | .set_antenna = ath10k_set_antenna, | ||
4326 | .get_antenna = ath10k_get_antenna, | ||
4259 | .restart_complete = ath10k_restart_complete, | 4327 | .restart_complete = ath10k_restart_complete, |
4260 | .get_survey = ath10k_get_survey, | 4328 | .get_survey = ath10k_get_survey, |
4261 | .set_bitrate_mask = ath10k_set_bitrate_mask, | 4329 | .set_bitrate_mask = ath10k_set_bitrate_mask, |
@@ -4605,6 +4673,18 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4605 | BIT(NL80211_IFTYPE_ADHOC) | | 4673 | BIT(NL80211_IFTYPE_ADHOC) | |
4606 | BIT(NL80211_IFTYPE_AP); | 4674 | BIT(NL80211_IFTYPE_AP); |
4607 | 4675 | ||
4676 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
4677 | /* TODO: Have to deal with 2x2 chips if/when the come out. */ | ||
4678 | ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK; | ||
4679 | ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK; | ||
4680 | } else { | ||
4681 | ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK; | ||
4682 | ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK; | ||
4683 | } | ||
4684 | |||
4685 | ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; | ||
4686 | ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; | ||
4687 | |||
4608 | if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) | 4688 | if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features)) |
4609 | ar->hw->wiphy->interface_modes |= | 4689 | ar->hw->wiphy->interface_modes |= |
4610 | BIT(NL80211_IFTYPE_P2P_CLIENT) | | 4690 | BIT(NL80211_IFTYPE_P2P_CLIENT) | |