tree-wide: replace config_enabled() with IS_ENABLED()
[cascardo/linux.git] / drivers / net / wireless / ath / ath10k / mac.c
index 4040f94..0bbd0a0 100644 (file)
@@ -62,6 +62,32 @@ static struct ieee80211_rate ath10k_rates[] = {
        { .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M },
 };
 
+static struct ieee80211_rate ath10k_rates_rev2[] = {
+       { .bitrate = 10,
+         .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_1M },
+       { .bitrate = 20,
+         .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_2M,
+         .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_2M,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 55,
+         .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_5_5M,
+         .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_5_5M,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+       { .bitrate = 110,
+         .hw_value = ATH10K_HW_RATE_REV2_CCK_LP_11M,
+         .hw_value_short = ATH10K_HW_RATE_REV2_CCK_SP_11M,
+         .flags = IEEE80211_RATE_SHORT_PREAMBLE },
+
+       { .bitrate = 60, .hw_value = ATH10K_HW_RATE_OFDM_6M },
+       { .bitrate = 90, .hw_value = ATH10K_HW_RATE_OFDM_9M },
+       { .bitrate = 120, .hw_value = ATH10K_HW_RATE_OFDM_12M },
+       { .bitrate = 180, .hw_value = ATH10K_HW_RATE_OFDM_18M },
+       { .bitrate = 240, .hw_value = ATH10K_HW_RATE_OFDM_24M },
+       { .bitrate = 360, .hw_value = ATH10K_HW_RATE_OFDM_36M },
+       { .bitrate = 480, .hw_value = ATH10K_HW_RATE_OFDM_48M },
+       { .bitrate = 540, .hw_value = ATH10K_HW_RATE_OFDM_54M },
+};
+
 #define ATH10K_MAC_FIRST_OFDM_RATE_IDX 4
 
 #define ath10k_a_rates (ath10k_rates + ATH10K_MAC_FIRST_OFDM_RATE_IDX)
@@ -70,6 +96,9 @@ static struct ieee80211_rate ath10k_rates[] = {
 #define ath10k_g_rates (ath10k_rates + 0)
 #define ath10k_g_rates_size (ARRAY_SIZE(ath10k_rates))
 
+#define ath10k_g_rates_rev2 (ath10k_rates_rev2 + 0)
+#define ath10k_g_rates_rev2_size (ARRAY_SIZE(ath10k_rates_rev2))
+
 static bool ath10k_mac_bitrate_is_cck(int bitrate)
 {
        switch (bitrate) {
@@ -773,6 +802,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 {
        struct ath10k_peer *peer, *tmp;
        int peer_id;
+       int i;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -789,6 +819,17 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
                        ar->peer_map[peer_id] = NULL;
                }
 
+               /* Double check that peer is properly un-referenced from
+                * the peer_map
+                */
+               for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) {
+                       if (ar->peer_map[i] == peer) {
+                               ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %p idx %d)\n",
+                                           peer->addr, peer, i);
+                               ar->peer_map[i] = NULL;
+                       }
+               }
+
                list_del(&peer->list);
                kfree(peer);
                ar->num_peers--;
@@ -799,6 +840,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id)
 static void ath10k_peer_cleanup_all(struct ath10k *ar)
 {
        struct ath10k_peer *peer, *tmp;
+       int i;
 
        lockdep_assert_held(&ar->conf_mutex);
 
@@ -807,6 +849,10 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar)
                list_del(&peer->list);
                kfree(peer);
        }
+
+       for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++)
+               ar->peer_map[i] = NULL;
+
        spin_unlock_bh(&ar->data_lock);
 
        ar->num_peers = 0;
@@ -2910,7 +2956,7 @@ static int ath10k_update_channel_list(struct ath10k *ar)
                        if (channel->flags & IEEE80211_CHAN_DISABLED)
                                continue;
 
-                       ch->allow_ht   = true;
+                       ch->allow_ht = true;
 
                        /* FIXME: when should we really allow VHT? */
                        ch->allow_vht = true;
@@ -2993,7 +3039,7 @@ static void ath10k_regd_update(struct ath10k *ar)
 
        regpair = ar->ath_common.regulatory.regpair;
 
-       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
+       if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
                nl_dfs_reg = ar->dfs_detector->region;
                wmi_dfs_reg = ath10k_mac_get_dfs_region(nl_dfs_reg);
        } else {
@@ -3022,7 +3068,7 @@ static void ath10k_reg_notifier(struct wiphy *wiphy,
 
        ath_reg_notifier_apply(wiphy, request, &ar->ath_common.regulatory);
 
-       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
+       if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector) {
                ath10k_dbg(ar, ATH10K_DBG_REGULATORY, "dfs region 0x%x\n",
                           request->dfs_region);
                result = ar->dfs_detector->set_dfs_domain(ar->dfs_detector,
@@ -3646,17 +3692,18 @@ void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work)
 
 static void ath10k_mac_txq_init(struct ieee80211_txq *txq)
 {
-       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+       struct ath10k_txq *artxq;
 
        if (!txq)
                return;
 
+       artxq = (void *)txq->drv_priv;
        INIT_LIST_HEAD(&artxq->list);
 }
 
 static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
 {
-       struct ath10k_txq *artxq = (void *)txq->drv_priv;
+       struct ath10k_txq *artxq;
        struct ath10k_skb_cb *cb;
        struct sk_buff *msdu;
        int msdu_id;
@@ -3664,6 +3711,7 @@ static void ath10k_mac_txq_unref(struct ath10k *ar, struct ieee80211_txq *txq)
        if (!txq)
                return;
 
+       artxq = (void *)txq->drv_priv;
        spin_lock_bh(&ar->txqs_lock);
        if (!list_empty(&artxq->list))
                list_del_init(&artxq->list);
@@ -3781,6 +3829,9 @@ void ath10k_mac_tx_push_pending(struct ath10k *ar)
        int ret;
        int max;
 
+       if (ar->htt.num_pending_tx >= (ar->htt.max_num_pending_tx / 2))
+               return;
+
        spin_lock_bh(&ar->txqs_lock);
        rcu_read_lock();
 
@@ -3826,12 +3877,16 @@ void __ath10k_scan_finish(struct ath10k *ar)
                break;
        case ATH10K_SCAN_RUNNING:
        case ATH10K_SCAN_ABORTING:
-               if (!ar->scan.is_roc)
-                       ieee80211_scan_completed(ar->hw,
-                                                (ar->scan.state ==
-                                                 ATH10K_SCAN_ABORTING));
-               else if (ar->scan.roc_notify)
+               if (!ar->scan.is_roc) {
+                       struct cfg80211_scan_info info = {
+                               .aborted = (ar->scan.state ==
+                                           ATH10K_SCAN_ABORTING),
+                       };
+
+                       ieee80211_scan_completed(ar->hw, &info);
+               } else if (ar->scan.roc_notify) {
                        ieee80211_remain_on_channel_expired(ar->hw);
+               }
                /* fall through */
        case ATH10K_SCAN_STARTING:
                ar->scan.state = ATH10K_SCAN_IDLE;
@@ -4051,9 +4106,7 @@ static void ath10k_mac_op_wake_tx_queue(struct ieee80211_hw *hw,
                list_add_tail(&artxq->list, &ar->txqs);
        spin_unlock_bh(&ar->txqs_lock);
 
-       if (ath10k_mac_tx_can_push(hw, txq))
-               tasklet_schedule(&ar->htt.txrx_compl_task);
-
+       ath10k_mac_tx_push_pending(ar);
        ath10k_htt_tx_txq_update(hw, txq);
 }
 
@@ -4194,6 +4247,9 @@ static struct ieee80211_sta_vht_cap ath10k_create_vht_cap(struct ath10k *ar)
                        mcs_map |= IEEE80211_VHT_MCS_NOT_SUPPORTED << (i * 2);
        }
 
+       if (ar->cfg_tx_chainmask <= 1)
+               vht_cap.cap &= ~IEEE80211_VHT_CAP_TXSTBC;
+
        vht_cap.vht_mcs.rx_mcs_map = cpu_to_le16(mcs_map);
        vht_cap.vht_mcs.tx_mcs_map = cpu_to_le16(mcs_map);
 
@@ -4231,7 +4287,7 @@ static struct ieee80211_sta_ht_cap ath10k_get_ht_cap(struct ath10k *ar)
                ht_cap.cap |= smps;
        }
 
-       if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC)
+       if (ar->ht_cap_info & WMI_HT_CAP_TX_STBC && (ar->cfg_tx_chainmask > 1))
                ht_cap.cap |= IEEE80211_HT_CAP_TX_STBC;
 
        if (ar->ht_cap_info & WMI_HT_CAP_RX_STBC) {
@@ -4467,6 +4523,19 @@ static int ath10k_start(struct ieee80211_hw *hw)
                }
        }
 
+       param = ar->wmi.pdev_param->enable_btcoex;
+       if (test_bit(WMI_SERVICE_COEX_GPIO, ar->wmi.svc_map) &&
+           test_bit(ATH10K_FW_FEATURE_BTCOEX_PARAM,
+                    ar->running_fw->fw_file.fw_features)) {
+               ret = ath10k_wmi_pdev_set_param(ar, param, 0);
+               if (ret) {
+                       ath10k_warn(ar,
+                                   "failed to set btcoex param: %d\n", ret);
+                       goto err_core_stop;
+               }
+               clear_bit(ATH10K_FLAG_BTCOEX, &ar->dev_flags);
+       }
+
        ar->num_started_vdevs = 0;
        ath10k_regd_update(ar);
 
@@ -5932,9 +6001,17 @@ static int ath10k_sta_state(struct ieee80211_hw *hw,
                                continue;
 
                        if (peer->sta == sta) {
-                               ath10k_warn(ar, "found sta peer %pM entry on vdev %i after it was supposedly removed\n",
-                                           sta->addr, arvif->vdev_id);
+                               ath10k_warn(ar, "found sta peer %pM (ptr %p id %d) entry on vdev %i after it was supposedly removed\n",
+                                           sta->addr, peer, i, arvif->vdev_id);
                                peer->sta = NULL;
+
+                               /* Clean up the peer object as well since we
+                                * must have failed to do this above.
+                                */
+                               list_del(&peer->list);
+                               ar->peer_map[i] = NULL;
+                               kfree(peer);
+                               ar->num_peers--;
                        }
                }
                spin_unlock_bh(&ar->data_lock);
@@ -7359,6 +7436,7 @@ static const struct ieee80211_ops ath10k_ops = {
 #endif
 #ifdef CONFIG_MAC80211_DEBUGFS
        .sta_add_debugfs                = ath10k_sta_add_debugfs,
+       .sta_statistics                 = ath10k_sta_statistics,
 #endif
 };
 
@@ -7428,21 +7506,32 @@ static const struct ieee80211_channel ath10k_5ghz_channels[] = {
 struct ath10k *ath10k_mac_create(size_t priv_size)
 {
        struct ieee80211_hw *hw;
+       struct ieee80211_ops *ops;
        struct ath10k *ar;
 
-       hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, &ath10k_ops);
-       if (!hw)
+       ops = kmemdup(&ath10k_ops, sizeof(ath10k_ops), GFP_KERNEL);
+       if (!ops)
                return NULL;
 
+       hw = ieee80211_alloc_hw(sizeof(struct ath10k) + priv_size, ops);
+       if (!hw) {
+               kfree(ops);
+               return NULL;
+       }
+
        ar = hw->priv;
        ar->hw = hw;
+       ar->ops = ops;
 
        return ar;
 }
 
 void ath10k_mac_destroy(struct ath10k *ar)
 {
+       struct ieee80211_ops *ops = ar->ops;
+
        ieee80211_free_hw(ar->hw);
+       kfree(ops);
 }
 
 static const struct ieee80211_iface_limit ath10k_if_limits[] = {
@@ -7695,8 +7784,14 @@ int ath10k_mac_register(struct ath10k *ar)
                band = &ar->mac.sbands[NL80211_BAND_2GHZ];
                band->n_channels = ARRAY_SIZE(ath10k_2ghz_channels);
                band->channels = channels;
-               band->n_bitrates = ath10k_g_rates_size;
-               band->bitrates = ath10k_g_rates;
+
+               if (ar->hw_params.cck_rate_map_rev2) {
+                       band->n_bitrates = ath10k_g_rates_rev2_size;
+                       band->bitrates = ath10k_g_rates_rev2;
+               } else {
+                       band->n_bitrates = ath10k_g_rates_size;
+                       band->bitrates = ath10k_g_rates;
+               }
 
                ar->hw->wiphy->bands[NL80211_BAND_2GHZ] = band;
        }
@@ -7860,7 +7955,7 @@ int ath10k_mac_register(struct ath10k *ar)
        if (!test_bit(ATH10K_FLAG_RAW_MODE, &ar->dev_flags))
                ar->hw->netdev_features = NETIF_F_HW_CSUM;
 
-       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) {
+       if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED)) {
                /* Init ath dfs pattern detector */
                ar->ath_common.debug_mask = ATH_DBG_DFS;
                ar->dfs_detector = dfs_pattern_detector_init(&ar->ath_common,
@@ -7870,6 +7965,15 @@ int ath10k_mac_register(struct ath10k *ar)
                        ath10k_warn(ar, "failed to initialise DFS pattern detector\n");
        }
 
+       /* Current wake_tx_queue implementation imposes a significant
+        * performance penalty in some setups. The tx scheduling code needs
+        * more work anyway so disable the wake_tx_queue unless firmware
+        * supports the pull-push mechanism.
+        */
+       if (!test_bit(ATH10K_FW_FEATURE_PEER_FLOW_CONTROL,
+                     ar->running_fw->fw_file.fw_features))
+               ar->ops->wake_tx_queue = NULL;
+
        ret = ath_regd_init(&ar->ath_common.regulatory, ar->hw->wiphy,
                            ath10k_reg_notifier);
        if (ret) {
@@ -7899,7 +8003,7 @@ err_unregister:
        ieee80211_unregister_hw(ar->hw);
 
 err_dfs_detector_exit:
-       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+       if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
                ar->dfs_detector->exit(ar->dfs_detector);
 
 err_free:
@@ -7914,7 +8018,7 @@ void ath10k_mac_unregister(struct ath10k *ar)
 {
        ieee80211_unregister_hw(ar->hw);
 
-       if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
+       if (IS_ENABLED(CONFIG_ATH10K_DFS_CERTIFIED) && ar->dfs_detector)
                ar->dfs_detector->exit(ar->dfs_detector);
 
        kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels);