mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-22 03:42:41 +00:00
638 lines
16 KiB
Diff
638 lines
16 KiB
Diff
From d515e964f7ce49ec3478135fb7dc36c05c7221da Mon Sep 17 00:00:00 2001
|
|
From: Sriram R <quic_srirrama@quicinc.com>
|
|
Date: Wed, 22 Dec 2021 12:08:29 +0530
|
|
Subject: [PATCH 02/10] ath12k: Update hw generic mac ops handling
|
|
|
|
Handle the below mac ops.
|
|
1. start/stop
|
|
2. get_antenna/set_antenna
|
|
3. set_rts_threshold
|
|
4. add_chanctx
|
|
5. remove_chanctx
|
|
|
|
Note that antenna/rts configs will have to be made link
|
|
specific configs so that they can updated individually.
|
|
|
|
Other feature specific ops with just 'hw' as arg
|
|
like config/configure_filter will be handled in monitor support.
|
|
|
|
reconfig_complete() will be handled in HW restart support.
|
|
|
|
Co-developed-by: P Praneesh <quic_ppranees@quicinc.com>
|
|
Signed-off-by: P Praneesh <quic_ppranees@quicinc.com>
|
|
Signed-off-by: Sriram R <quic_srirrama@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath12k/mac.c | 279 +++++++++++++++++++++-------------
|
|
1 file changed, 172 insertions(+), 107 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/mac.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/mac.c
|
|
@@ -621,6 +621,33 @@ struct ath12k_vif *ath12k_mac_get_arvif_
|
|
return NULL;
|
|
}
|
|
|
|
+static struct ath12k *ath12k_mac_get_ar_by_band(struct ieee80211_hw *hw,
|
|
+ enum nl80211_band band)
|
|
+{
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int i;
|
|
+
|
|
+ ar = ah->radio;
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ if (ar->mac.sbands[band].channels)
|
|
+ return ar;
|
|
+ ar++;
|
|
+ }
|
|
+ return NULL;
|
|
+}
|
|
+
|
|
+static struct ath12k *ath12k_get_ar_by_ctx(struct ieee80211_hw *hw,
|
|
+ struct ieee80211_chanctx_conf *ctx)
|
|
+{
|
|
+ if (!ctx)
|
|
+ return NULL;
|
|
+
|
|
+ /* TODO 5G low high split radio changes */
|
|
+
|
|
+ return ath12k_mac_get_ar_by_band(hw, ctx->def.chan->band);
|
|
+}
|
|
+
|
|
struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id)
|
|
{
|
|
int i;
|
|
@@ -1150,46 +1177,54 @@ static int ath12k_mac_monitor_stop(struc
|
|
|
|
static int ath12k_mac_op_config(struct ieee80211_hw *hw, u32 changed)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
struct ieee80211_conf *conf = &hw->conf;
|
|
- int ret;
|
|
+ int ret, i;
|
|
|
|
- mutex_lock(&ar->conf_mutex);
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
|
|
- if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
|
- if (conf->flags & IEEE80211_CONF_MONITOR) {
|
|
- set_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags);
|
|
- if (test_bit(MONITOR_VDEV_CREATED,
|
|
- &ar->monitor_flags))
|
|
- goto exit;
|
|
+ ar = ah->radio;
|
|
|
|
- ret = ath12k_mac_monitor_vdev_create(ar);
|
|
- if (ret)
|
|
- goto exit;
|
|
- ret = ath12k_mac_monitor_start(ar);
|
|
- if (ret)
|
|
- goto err_mon_del;
|
|
- } else {
|
|
- clear_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags);
|
|
- if (!test_bit(MONITOR_VDEV_CREATED,
|
|
- &ar->monitor_flags))
|
|
- goto exit;
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
|
|
- ret = ath12k_mac_monitor_stop(ar);
|
|
- if (ret)
|
|
- goto exit;
|
|
- ath12k_mac_monitor_vdev_delete(ar);
|
|
+ if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
|
|
+ if (conf->flags & IEEE80211_CONF_MONITOR) {
|
|
+ set_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags);
|
|
+ if (test_bit(MONITOR_VDEV_CREATED,
|
|
+ &ar->monitor_flags))
|
|
+ goto out;
|
|
+
|
|
+ ret = ath12k_mac_monitor_vdev_create(ar);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+ ret = ath12k_mac_monitor_start(ar);
|
|
+ if (ret) {
|
|
+ ath12k_mac_monitor_vdev_delete(ar);
|
|
+ goto out;
|
|
+ }
|
|
+ } else {
|
|
+ clear_bit(MONITOR_CONF_ENABLED, &ar->monitor_flags);
|
|
+ if (!test_bit(MONITOR_VDEV_CREATED,
|
|
+ &ar->monitor_flags))
|
|
+ goto out;
|
|
+
|
|
+ ret = ath12k_mac_monitor_stop(ar);
|
|
+ if (ret)
|
|
+ goto out;
|
|
+
|
|
+ ath12k_mac_monitor_vdev_delete(ar);
|
|
+ }
|
|
}
|
|
+out:
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ ar++;
|
|
}
|
|
|
|
-exit:
|
|
- mutex_unlock(&ar->conf_mutex);
|
|
- return ret;
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
|
|
-err_mon_del:
|
|
- ath12k_mac_monitor_vdev_delete(ar);
|
|
- mutex_unlock(&ar->conf_mutex);
|
|
- return 0;
|
|
+ return ret;
|
|
}
|
|
|
|
static void ath12k_mac_setup_bcn_tmpl_vif_params(struct ath12k_vif *arvif,
|
|
@@ -5143,11 +5178,11 @@ static void ath12k_mac_op_sta_set_4addr(
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_sta *sta, bool enabled)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
struct ath12k_sta *arsta = (struct ath12k_sta *)sta->drv_priv;
|
|
|
|
if (enabled && !arsta->use_4addr_set) {
|
|
- ieee80211_queue_work(ar->hw, &arsta->set_4addr_wk);
|
|
+ ieee80211_queue_work(ah->hw, &arsta->set_4addr_wk);
|
|
arsta->use_4addr_set = true;
|
|
}
|
|
}
|
|
@@ -5590,15 +5625,6 @@ static void ath12k_mac_setup_ht_vht_cap(
|
|
}
|
|
}
|
|
|
|
-static int ath12k_check_chain_mask(struct ath12k *ar, u32 ant, bool is_tx_ant)
|
|
-{
|
|
- /* TODO: Check the request chainmask against the supported
|
|
- * chainmask table which is advertised in extented_service_ready event
|
|
- */
|
|
-
|
|
- return 0;
|
|
-}
|
|
-
|
|
static void ath12k_gen_ppe_thresh(struct ath12k_ppe_threshold *fw_ppet,
|
|
u8 *he_ppet)
|
|
{
|
|
@@ -6075,11 +6101,12 @@ static int __ath12k_set_antenna(struct a
|
|
|
|
lockdep_assert_held(&ar->conf_mutex);
|
|
|
|
- if (ath12k_check_chain_mask(ar, tx_ant, true))
|
|
- return -EINVAL;
|
|
-
|
|
- if (ath12k_check_chain_mask(ar, rx_ant, false))
|
|
- return -EINVAL;
|
|
+ /* Since we advertised the max cap of all radios combined during wiphy
|
|
+ * registration, ensure we dont set the antenna config higher than our
|
|
+ * limits
|
|
+ */
|
|
+ tx_ant = min_t(u32, tx_ant, ar->pdev->cap.tx_chain_mask);
|
|
+ rx_ant = min_t(u32, rx_ant, ar->pdev->cap.rx_chain_mask);
|
|
|
|
ar->cfg_tx_chainmask = tx_ant;
|
|
ar->cfg_rx_chainmask = rx_ant;
|
|
@@ -6315,10 +6342,10 @@ static void ath12k_mac_op_tx(struct ieee
|
|
struct sk_buff *skb)
|
|
{
|
|
struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb);
|
|
- struct ath12k *ar = hw->priv;
|
|
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
|
|
struct ieee80211_vif *vif = info->control.vif;
|
|
struct ath12k_vif *arvif = ath12k_vif_to_arvif(vif);
|
|
+ struct ath12k *ar = arvif->ar;
|
|
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
|
|
struct ieee80211_key_conf *key = info->control.hw_key;
|
|
struct ath12k_sta *arsta = NULL;
|
|
@@ -6397,9 +6424,8 @@ static int ath12k_mac_config_mon_status_
|
|
return ret;
|
|
}
|
|
|
|
-static int ath12k_mac_op_start(struct ieee80211_hw *hw)
|
|
+static int ath12k_mac_radio_start(struct ath12k *ar)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
struct ath12k_base *ab = ar->ab;
|
|
struct ath12k_pdev *pdev = ar->pdev;
|
|
int ret;
|
|
@@ -6426,14 +6452,14 @@ static int ath12k_mac_op_start(struct ie
|
|
1, pdev->pdev_id);
|
|
|
|
if (ret) {
|
|
- ath12k_err(ar->ab, "failed to enable PMF QOS: (%d\n", ret);
|
|
+ ath12k_err(ab, "failed to enable PMF QOS: (%d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_DYNAMIC_BW, 1,
|
|
pdev->pdev_id);
|
|
if (ret) {
|
|
- ath12k_err(ar->ab, "failed to enable dynamic bw: %d\n", ret);
|
|
+ ath12k_err(ab, "failed to enable dynamic bw: %d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
@@ -6463,7 +6489,7 @@ static int ath12k_mac_op_start(struct ie
|
|
1, pdev->pdev_id);
|
|
|
|
if (ret) {
|
|
- ath12k_err(ar->ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);
|
|
+ ath12k_err(ab, "failed to enable MESH MCAST ENABLE: (%d\n", ret);
|
|
goto err;
|
|
}
|
|
|
|
@@ -6493,7 +6519,7 @@ static int ath12k_mac_op_start(struct ie
|
|
}
|
|
|
|
if (ret == -ENOTSUPP)
|
|
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
|
+ ath12k_dbg(ab, ATH12K_DBG_MAC,
|
|
"monitor status config is not yet supported");
|
|
|
|
/* Configure the hash seed for hash based reo dest ring selection */
|
|
@@ -6522,9 +6548,8 @@ err:
|
|
return ret;
|
|
}
|
|
|
|
-static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
|
|
+static void ath12k_mac_radio_stop(struct ath12k *ar)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
struct htt_ppdu_stats_info *ppdu_stats, *tmp;
|
|
int ret;
|
|
|
|
@@ -6561,6 +6586,62 @@ static void ath12k_mac_op_stop(struct ie
|
|
spin_unlock_bh(&ar->data_lock);
|
|
}
|
|
|
|
+static int ath12k_mac_op_start(struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ struct ath12k_base *ab;
|
|
+ int i;
|
|
+ int ret;
|
|
+
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
+ ar = ah->radio;
|
|
+ ab = ar->ab;
|
|
+
|
|
+ /* TODO Maintain state for ah? */
|
|
+
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ ab = ar->ab;
|
|
+ ret = ath12k_mac_radio_start(ar);
|
|
+ if (ret) {
|
|
+ ath12k_err(ab, "fail to start mac operations in radio %d ret %d\n",
|
|
+ i, ret);
|
|
+ goto err;
|
|
+ }
|
|
+ ar++;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
+ return 0;
|
|
+err:
|
|
+ ar = ah->radio;
|
|
+ for (i = i - 1; i >= 0; i--) {
|
|
+ ath12k_mac_radio_stop(ar);
|
|
+ ar++;
|
|
+ }
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
+ return ret;
|
|
+}
|
|
+
|
|
+static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
|
|
+{
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int i;
|
|
+
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
+ ar = ah->radio;
|
|
+
|
|
+ /* TODO Maintain state for ah? */
|
|
+
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ ath12k_mac_radio_stop(ar);
|
|
+ ar++;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
+}
|
|
+
|
|
static u8
|
|
ath12k_mac_get_vdev_stats_id(struct ath12k_vif *arvif)
|
|
{
|
|
@@ -7098,38 +7179,71 @@ static void ath12k_mac_op_configure_filt
|
|
unsigned int *total_flags,
|
|
u64 multicast)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int i;
|
|
|
|
- mutex_lock(&ar->conf_mutex);
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
|
|
- *total_flags &= SUPPORTED_FILTERS;
|
|
- ar->filter_flags = *total_flags;
|
|
+ ar = ah->radio;
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
|
|
- mutex_unlock(&ar->conf_mutex);
|
|
+ *total_flags &= SUPPORTED_FILTERS;
|
|
+ ar->filter_flags = *total_flags;
|
|
+
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ ar++;
|
|
+ }
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
}
|
|
|
|
+/* TODO Also support link based antenna configs, below might not be accurate */
|
|
static int ath12k_mac_op_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int antennas_rx = 0, antennas_tx = 0, i;
|
|
|
|
- mutex_lock(&ar->conf_mutex);
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
|
|
- *tx_ant = ar->cfg_tx_chainmask;
|
|
- *rx_ant = ar->cfg_rx_chainmask;
|
|
+ ar = ah->radio;
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
|
|
- mutex_unlock(&ar->conf_mutex);
|
|
+ antennas_tx = max_t(u32, antennas_tx, ar->cfg_tx_chainmask);
|
|
+ antennas_rx = max_t(u32, antennas_rx, ar->cfg_rx_chainmask);
|
|
+
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+ ar++;
|
|
+ }
|
|
+
|
|
+ *tx_ant = antennas_tx;
|
|
+ *rx_ant = antennas_rx;
|
|
+
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
- int ret;
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int ret = 0, i;
|
|
|
|
- mutex_lock(&ar->conf_mutex);
|
|
- ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);
|
|
- mutex_unlock(&ar->conf_mutex);
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
+
|
|
+ ar = ah->radio;
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+ ret = __ath12k_set_antenna(ar, tx_ant, rx_ant);
|
|
+ mutex_unlock(&ar->conf_mutex);
|
|
+
|
|
+ ar++;
|
|
+ }
|
|
+
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
|
|
return ret;
|
|
}
|
|
@@ -7170,10 +7284,14 @@ static int ath12k_mac_op_ampdu_action(st
|
|
static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
|
|
struct ieee80211_chanctx_conf *ctx)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
- struct ath12k_base *ab = ar->ab;
|
|
+ struct ath12k *ar;
|
|
|
|
- ath12k_dbg(ab, ATH12K_DBG_MAC,
|
|
+ ar = ath12k_get_ar_by_ctx(hw, ctx);
|
|
+
|
|
+ if (!ar)
|
|
+ return -EINVAL;
|
|
+
|
|
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
|
"mac chanctx add freq %u width %d ptr %pK\n",
|
|
ctx->def.chan->center_freq, ctx->def.width, ctx);
|
|
|
|
@@ -7194,10 +7312,14 @@ static int ath12k_mac_op_add_chanctx(str
|
|
static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
|
|
struct ieee80211_chanctx_conf *ctx)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
- struct ath12k_base *ab = ar->ab;
|
|
+ struct ath12k *ar;
|
|
|
|
- ath12k_dbg(ab, ATH12K_DBG_MAC,
|
|
+ ar = ath12k_get_ar_by_ctx(hw, ctx);
|
|
+
|
|
+ if (!ar)
|
|
+ return;
|
|
+
|
|
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
|
"mac chanctx remove freq %u width %d ptr %pK\n",
|
|
ctx->def.chan->center_freq, ctx->def.width, ctx);
|
|
|
|
@@ -8409,13 +8531,28 @@ ath12k_set_vdev_param_to_all_vifs(struct
|
|
|
|
/* mac80211 stores device specific RTS/Fragmentation threshold value,
|
|
* this is set interface specific to firmware from ath12k driver
|
|
+ * TODO Move to link specific config
|
|
*/
|
|
static int ath12k_mac_op_set_rts_threshold(struct ieee80211_hw *hw, u32 value)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int i, ret;
|
|
int param_id = WMI_VDEV_PARAM_RTS_THRESHOLD;
|
|
|
|
- return ath12k_set_vdev_param_to_all_vifs(ar, param_id, value);
|
|
+ ar = ah->radio;
|
|
+
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ ret = ath12k_set_vdev_param_to_all_vifs(ar, param_id, value);
|
|
+ if (ret) {
|
|
+ ath12k_warn(ar->ab, "failed to set RTS config for all vdevs of pdev %d",
|
|
+ ar->pdev->pdev_id);
|
|
+ break;
|
|
+ }
|
|
+ ar++;
|
|
+ }
|
|
+
|
|
+ return ret;
|
|
}
|
|
|
|
static int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw, u32 value)
|
|
@@ -8433,33 +8570,63 @@ static int ath12k_mac_op_set_frag_thresh
|
|
return -EOPNOTSUPP;
|
|
}
|
|
|
|
-static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
- u32 queues, bool drop)
|
|
+static void ath12k_mac_flush(struct ath12k *ar)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k_base *ab = ar->ab;
|
|
long time_left;
|
|
|
|
- if (drop)
|
|
- return;
|
|
+ lockdep_assert_held(&ar->ab->ah->conf_mutex);
|
|
|
|
time_left = wait_event_timeout(ar->dp.tx_empty_waitq,
|
|
(atomic_read(&ar->dp.num_tx_pending) == 0),
|
|
ATH12K_FLUSH_TIMEOUT);
|
|
if (time_left == 0)
|
|
- ath12k_warn(ar->ab, "failed to flush transmit queue %ld\n", time_left);
|
|
+ ath12k_warn(ab, "failed to flush transmit queue %ld\n", time_left);
|
|
|
|
time_left = wait_event_timeout(ar->txmgmt_empty_waitq,
|
|
(atomic_read(&ar->num_pending_mgmt_tx) == 0),
|
|
ATH12K_FLUSH_TIMEOUT);
|
|
if (time_left == 0)
|
|
- ath12k_warn(ar->ab, "failed to flush mgmt transmit queue %ld\n",
|
|
+ ath12k_warn(ab, "failed to flush mgmt transmit queue %ld\n",
|
|
time_left);
|
|
|
|
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
|
|
+ ath12k_dbg(ab, ATH12K_DBG_MAC,
|
|
"mac mgmt tx flush mgmt pending %d\n",
|
|
atomic_read(&ar->num_pending_mgmt_tx));
|
|
}
|
|
|
|
+static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|
+ u32 queues, bool drop)
|
|
+{
|
|
+ struct ath12k_hw *ah = hw->priv;
|
|
+ struct ath12k *ar;
|
|
+ int i;
|
|
+
|
|
+ if (drop)
|
|
+ return;
|
|
+
|
|
+ mutex_lock(&ah->conf_mutex);
|
|
+
|
|
+ if (!vif) {
|
|
+ /* FIXME: Need to identify which radio to flush.
|
|
+ * Until flush all the device if vif NULL
|
|
+ */
|
|
+ ar = ah->radio;
|
|
+ for (i = 0; i < ah->num_radio; i++) {
|
|
+ ath12k_mac_flush(ar);
|
|
+ ar++;
|
|
+ }
|
|
+ } else {
|
|
+ ar = ath12k_get_ar_by_vif(hw, vif);
|
|
+ if (!ar) {
|
|
+ goto out;
|
|
+ }
|
|
+ ath12k_mac_flush(ar);
|
|
+ }
|
|
+out:
|
|
+ mutex_unlock(&ah->conf_mutex);
|
|
+}
|
|
+
|
|
static int
|
|
ath12k_mac_bitrate_mask_num_ht_rates(struct ath12k *ar,
|
|
enum nl80211_band band,
|
|
@@ -9189,6 +9356,7 @@ static void
|
|
ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
|
|
enum ieee80211_reconfig_type reconfig_type)
|
|
{
|
|
+ /* TODO Handle hw restart */
|
|
struct ath12k *ar = hw->priv;
|
|
|
|
if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
|
|
@@ -9241,38 +9409,55 @@ ath12k_mac_update_bss_chan_survey(struct
|
|
static int ath12k_mac_op_get_survey(struct ieee80211_hw *hw, int idx,
|
|
struct survey_info *survey)
|
|
{
|
|
- struct ath12k *ar = hw->priv;
|
|
+ struct ath12k *ar;
|
|
struct ieee80211_supported_band *sband;
|
|
struct survey_info *ar_survey;
|
|
int ret = 0;
|
|
+ enum nl80211_band band;
|
|
|
|
if (idx >= ATH12K_NUM_CHANS)
|
|
return -ENOENT;
|
|
|
|
- ar_survey = &ar->survey[idx];
|
|
-
|
|
- mutex_lock(&ar->conf_mutex);
|
|
-
|
|
+ band = NL80211_BAND_2GHZ;
|
|
sband = hw->wiphy->bands[NL80211_BAND_2GHZ];
|
|
if (sband && idx >= sband->n_channels) {
|
|
idx -= sband->n_channels;
|
|
sband = NULL;
|
|
}
|
|
|
|
- if (!sband)
|
|
+ /* TODO: If 5G HB/LB are split across two radios then it requires
|
|
+ * idx check as well
|
|
+ */
|
|
+ if (!sband) {
|
|
sband = hw->wiphy->bands[NL80211_BAND_5GHZ];
|
|
+ band = NL80211_BAND_5GHZ;
|
|
+ }
|
|
+
|
|
if (sband && idx >= sband->n_channels) {
|
|
idx -= sband->n_channels;
|
|
sband = NULL;
|
|
}
|
|
|
|
- if (!sband)
|
|
+ if (!sband) {
|
|
sband = hw->wiphy->bands[NL80211_BAND_6GHZ];
|
|
+ band = NL80211_BAND_6GHZ;
|
|
+ }
|
|
+
|
|
if (!sband || idx >= sband->n_channels) {
|
|
ret = -ENOENT;
|
|
goto exit;
|
|
}
|
|
|
|
+ ar = ath12k_mac_get_ar_by_band(hw, band);
|
|
+ if (!ar) {
|
|
+ ret = -ENOENT;
|
|
+ goto exit;
|
|
+ }
|
|
+
|
|
+ ar_survey = &ar->survey[idx];
|
|
+
|
|
+ mutex_lock(&ar->conf_mutex);
|
|
+
|
|
ath12k_mac_update_bss_chan_survey(ar, &sband->channels[idx]);
|
|
|
|
spin_lock_bh(&ar->data_lock);
|
|
@@ -9284,8 +9469,9 @@ static int ath12k_mac_op_get_survey(stru
|
|
if (ar->rx_channel == survey->channel)
|
|
survey->filled |= SURVEY_INFO_IN_USE;
|
|
|
|
-exit:
|
|
mutex_unlock(&ar->conf_mutex);
|
|
+
|
|
+exit:
|
|
return ret;
|
|
}
|
|
|