diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k/mac.c')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 43 |
1 files changed, 37 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index ebc12c521fe0..55c823f983c7 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -802,6 +802,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) | |||
802 | { | 802 | { |
803 | struct ath10k_peer *peer, *tmp; | 803 | struct ath10k_peer *peer, *tmp; |
804 | int peer_id; | 804 | int peer_id; |
805 | int i; | ||
805 | 806 | ||
806 | lockdep_assert_held(&ar->conf_mutex); | 807 | lockdep_assert_held(&ar->conf_mutex); |
807 | 808 | ||
@@ -818,6 +819,17 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) | |||
818 | ar->peer_map[peer_id] = NULL; | 819 | ar->peer_map[peer_id] = NULL; |
819 | } | 820 | } |
820 | 821 | ||
822 | /* Double check that peer is properly un-referenced from | ||
823 | * the peer_map | ||
824 | */ | ||
825 | for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { | ||
826 | if (ar->peer_map[i] == peer) { | ||
827 | ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n", | ||
828 | peer->addr, peer, i); | ||
829 | ar->peer_map[i] = NULL; | ||
830 | } | ||
831 | } | ||
832 | |||
821 | list_del(&peer->list); | 833 | list_del(&peer->list); |
822 | kfree(peer); | 834 | kfree(peer); |
823 | ar->num_peers--; | 835 | ar->num_peers--; |
@@ -828,6 +840,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) | |||
828 | static void ath10k_peer_cleanup_all(struct ath10k *ar) | 840 | static void ath10k_peer_cleanup_all(struct ath10k *ar) |
829 | { | 841 | { |
830 | struct ath10k_peer *peer, *tmp; | 842 | struct ath10k_peer *peer, *tmp; |
843 | int i; | ||
831 | 844 | ||
832 | lockdep_assert_held(&ar->conf_mutex); | 845 | lockdep_assert_held(&ar->conf_mutex); |
833 | 846 | ||
@@ -836,6 +849,10 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar) | |||
836 | list_del(&peer->list); | 849 | list_del(&peer->list); |
837 | kfree(peer); | 850 | kfree(peer); |
838 | } | 851 | } |
852 | |||
853 | for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) | ||
854 | ar->peer_map[i] = NULL; | ||
855 | |||
839 | spin_unlock_bh(&ar->data_lock); | 856 | spin_unlock_bh(&ar->data_lock); |
840 | 857 | ||
841 | ar->num_peers = 0; | 858 | ar->num_peers = 0; |
@@ -2939,7 +2956,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) | |||
2939 | if (channel->flags & IEEE80211_CHAN_DISABLED) | 2956 | if (channel->flags & IEEE80211_CHAN_DISABLED) |
2940 | continue; | 2957 | continue; |
2941 | 2958 | ||
2942 | ch->allow_ht = true; | 2959 | ch->allow_ht = true; |
2943 | 2960 | ||
2944 | /* FIXME: when should we really allow VHT? */ | 2961 | /* FIXME: when should we really allow VHT? */ |
2945 | ch->allow_vht = true; | 2962 | ch->allow_vht = true; |
@@ -3675,17 +3692,18 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work) | |||
3675 | 3692 | ||
3676 | static void ath10k_mac_txq_init(struct ieee80211_txq *txq) | 3693 | static void ath10k_mac_txq_init(struct ieee80211_txq *txq) |
3677 | { | 3694 | { |
3678 | struct ath10k_txq *artxq = (void *)txq->drv_priv; | 3695 | struct ath10k_txq *artxq; |
3679 | 3696 | ||
3680 | if (!txq) | 3697 | if (!txq) |
3681 | return; | 3698 | return; |
3682 | 3699 | ||
3700 | artxq = (void *)txq->drv_priv; | ||
3683 | INIT_LIST_HEAD(&artxq->list); | 3701 | INIT_LIST_HEAD(&artxq->list); |
3684 | } | 3702 | } |
3685 | 3703 | ||
3686 | static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) | 3704 | static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) |
3687 | { | 3705 | { |
3688 | struct ath10k_txq *artxq = (void *)txq->drv_priv; | 3706 | struct ath10k_txq *artxq; |
3689 | struct ath10k_skb_cb *cb; | 3707 | struct ath10k_skb_cb *cb; |
3690 | struct sk_buff *msdu; | 3708 | struct sk_buff *msdu; |
3691 | int msdu_id; | 3709 | int msdu_id; |
@@ -3693,6 +3711,7 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq) | |||
3693 | if (!txq) | 3711 | if (!txq) |
3694 | return; | 3712 | return; |
3695 | 3713 | ||
3714 | artxq = (void *)txq->drv_priv; | ||
3696 | spin_lock_bh(&ar->txqs_lock); | 3715 | spin_lock_bh(&ar->txqs_lock); |
3697 | if (!list_empty(&artxq->list)) | 3716 | if (!list_empty(&artxq->list)) |
3698 | list_del_init(&artxq->list); | 3717 | list_del_init(&artxq->list); |
@@ -4228,6 +4247,9 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar) | |||
4228 | mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); | 4247 | mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2); |
4229 | } | 4248 | } |
4230 | 4249 | ||
4250 | if (ar->cfg_tx_chainmask <= 1) | ||
4251 | vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC; | ||
4252 | |||
4231 | vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); | 4253 | vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map); |
4232 | vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); | 4254 | vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map); |
4233 | 4255 | ||
@@ -4265,7 +4287,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar) | |||
4265 | ht_cap.cap |= smps; | 4287 | ht_cap.cap |= smps; |
4266 | } | 4288 | } |
4267 | 4289 | ||
4268 | if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC) | 4290 | if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC && (ar->cfg_tx_chainmask > 1)) |
4269 | ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; | 4291 | ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC; |
4270 | 4292 | ||
4271 | if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { | 4293 | if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) { |
@@ -5979,9 +6001,17 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
5979 | continue; | 6001 | continue; |
5980 | 6002 | ||
5981 | if (peer->sta == sta) { | 6003 | if (peer->sta == sta) { |
5982 | ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n", | 6004 | ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n", |
5983 | sta->addr, arvif->vdev_id); | 6005 | sta->addr, peer, i, arvif->vdev_id); |
5984 | peer->sta = NULL; | 6006 | peer->sta = NULL; |
6007 | |||
6008 | /* Clean up the peer object as well since we | ||
6009 | * must have failed to do this above. | ||
6010 | */ | ||
6011 | list_del(&peer->list); | ||
6012 | ar->peer_map[i] = NULL; | ||
6013 | kfree(peer); | ||
6014 | ar->num_peers--; | ||
5985 | } | 6015 | } |
5986 | } | 6016 | } |
5987 | spin_unlock_bh(&ar->data_lock); | 6017 | spin_unlock_bh(&ar->data_lock); |
@@ -7406,6 +7436,7 @@ static const struct ieee80211_ops ath10k_ops = { | |||
7406 | #endif | 7436 | #endif |
7407 | #ifdef CONFIG_MAC80211_DEBUGFS | 7437 | #ifdef CONFIG_MAC80211_DEBUGFS |
7408 | .sta_add_debugfs = ath10k_sta_add_debugfs, | 7438 | .sta_add_debugfs = ath10k_sta_add_debugfs, |
7439 | .sta_statistics = ath10k_sta_statistics, | ||
7409 | #endif | 7440 | #endif |
7410 | }; | 7441 | }; |
7411 | 7442 | ||