Commit a9aefb3b authored by Ben Greear's avatar Ben Greear Committed by Kalle Valo

ath10k: improve vdev map handling

Check vdev map has space before calling ffs,
fix invalid cleanup in failure to create vdev
case.

Open-code the BIT() logic since BIT does not properly
handle 64-bit bitfields and future patches will make
use of larger bitfields.
Signed-off-by: default avatarBen Greear <greearb@candelatech.com>
Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent b7967dc7
...@@ -597,14 +597,14 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) ...@@ -597,14 +597,14 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex); lockdep_assert_held(&ar->conf_mutex);
bit = ffs(ar->free_vdev_map); if (ar->free_vdev_map == 0) {
if (bit == 0) {
ath10k_warn("failed to find free vdev id for monitor vdev\n"); ath10k_warn("failed to find free vdev id for monitor vdev\n");
return -ENOMEM; return -ENOMEM;
} }
bit = ffs(ar->free_vdev_map);
ar->monitor_vdev_id = bit - 1; ar->monitor_vdev_id = bit - 1;
ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id,
WMI_VDEV_TYPE_MONITOR, WMI_VDEV_TYPE_MONITOR,
...@@ -612,20 +612,14 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) ...@@ -612,20 +612,14 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar)
if (ret) { if (ret) {
ath10k_warn("failed to request monitor vdev %i creation: %d\n", ath10k_warn("failed to request monitor vdev %i creation: %d\n",
ar->monitor_vdev_id, ret); ar->monitor_vdev_id, ret);
goto vdev_fail; return ret;
} }
ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id);
ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d created\n", ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d created\n",
ar->monitor_vdev_id); ar->monitor_vdev_id);
return 0; return 0;
vdev_fail:
/*
* Restore the ID to the global map.
*/
ar->free_vdev_map |= 1 << (ar->monitor_vdev_id);
return ret;
} }
static int ath10k_monitor_vdev_delete(struct ath10k *ar) static int ath10k_monitor_vdev_delete(struct ath10k *ar)
...@@ -641,7 +635,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar) ...@@ -641,7 +635,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar)
return ret; return ret;
} }
ar->free_vdev_map |= 1 << (ar->monitor_vdev_id); ar->free_vdev_map |= 1 << ar->monitor_vdev_id;
ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", ath10k_dbg(ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n",
ar->monitor_vdev_id); ar->monitor_vdev_id);
...@@ -2780,11 +2774,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ...@@ -2780,11 +2774,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work); INIT_WORK(&arvif->wep_key_work, ath10k_tx_wep_key_work);
INIT_LIST_HEAD(&arvif->list); INIT_LIST_HEAD(&arvif->list);
bit = ffs(ar->free_vdev_map); if (ar->free_vdev_map == 0) {
if (bit == 0) { ath10k_warn("Free vdev map is empty, no more interfaces allowed.\n");
ret = -EBUSY; ret = -EBUSY;
goto err; goto err;
} }
bit = ffs(ar->free_vdev_map);
arvif->vdev_id = bit - 1; arvif->vdev_id = bit - 1;
arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE;
...@@ -2827,7 +2822,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ...@@ -2827,7 +2822,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
goto err; goto err;
} }
ar->free_vdev_map &= ~BIT(arvif->vdev_id); ar->free_vdev_map &= ~(1 << arvif->vdev_id);
list_add(&arvif->list, &ar->arvifs); list_add(&arvif->list, &ar->arvifs);
vdev_param = ar->wmi.vdev_param->def_keyid; vdev_param = ar->wmi.vdev_param->def_keyid;
...@@ -2920,7 +2915,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, ...@@ -2920,7 +2915,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
err_vdev_delete: err_vdev_delete:
ath10k_wmi_vdev_delete(ar, arvif->vdev_id); ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
ar->free_vdev_map &= ~BIT(arvif->vdev_id); ar->free_vdev_map |= 1 << arvif->vdev_id;
list_del(&arvif->list); list_del(&arvif->list);
err: err:
...@@ -2956,7 +2951,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, ...@@ -2956,7 +2951,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
ath10k_warn("failed to stop spectral for vdev %i: %d\n", ath10k_warn("failed to stop spectral for vdev %i: %d\n",
arvif->vdev_id, ret); arvif->vdev_id, ret);
ar->free_vdev_map |= 1 << (arvif->vdev_id); ar->free_vdev_map |= 1 << arvif->vdev_id;
list_del(&arvif->list); list_del(&arvif->list);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { if (arvif->vdev_type == WMI_VDEV_TYPE_AP) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment