[PATCH 2/2] wifi: wlcore: unwind failed interface additions
From: Jiale Yao
Date: Sun Oct 18 2026 - 21:33:13 EST
wl12xx_init_vif_data() allocates per-interface host resources before
firmware setup. Later failures return without releasing those resources,
and failures after role enablement also leave the firmware role active
because mac80211 does not call remove_interface.
Factor the per-vif resource release into a helper, use it from removal
and add failure paths, and disable an enabled role when subsequent
initialization fails.
Fixes: 2f01a1f58889 ("wl12xx: add driver")
Signed-off-by: Jiale Yao <yaojiale02@xxxxxxx>
---
drivers/net/wireless/ti/wlcore/main.c | 66 +++++++++++++++++----------
1 file changed, 42 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 26aabf4ea127..9a0350b9d280 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -2374,6 +2374,30 @@ static int wl12xx_init_vif_data(struct wl1271 *wl, struct ieee80211_vif *vif)
return 0;
}
+static void wl12xx_deinit_vif_data(struct wl1271 *wl,
+ struct wl12xx_vif *wlvif)
+{
+ int i;
+
+ if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
+ wlvif->bss_type == BSS_TYPE_IBSS) {
+ wlvif->sta.hlid = WL12XX_INVALID_LINK_ID;
+ wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx);
+ wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx);
+ wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx);
+ wlcore_free_klv_template(wl, &wlvif->sta.klv_template_id);
+ } else {
+ wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
+ wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
+ wl12xx_free_rate_policy(wl, &wlvif->ap.mgmt_rate_idx);
+ wl12xx_free_rate_policy(wl, &wlvif->ap.bcast_rate_idx);
+ for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
+ wl12xx_free_rate_policy(wl,
+ &wlvif->ap.ucast_rate_idx[i]);
+ wl1271_free_ap_keys(wl, wlvif);
+ }
+}
+
static int wl12xx_init_fw(struct wl1271 *wl)
{
struct wlcore_platdev_data *pdev_data = dev_get_platdata(&wl->pdev->dev);
@@ -2633,12 +2657,12 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
role_type = wl12xx_get_role_type(wl, wlvif);
if (role_type == WL12XX_INVALID_ROLE_TYPE) {
ret = -EINVAL;
- goto out_unlock;
+ goto out_deinit;
}
ret = wlcore_allocate_hw_queue_base(wl, wlvif);
if (ret < 0)
- goto out_unlock;
+ goto out_deinit;
/*
* TODO: after the nvs issue will be solved, move this block
@@ -2653,7 +2677,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
ret = wl12xx_init_fw(wl);
if (ret < 0)
- goto out_unlock;
+ goto out_deinit;
}
/*
@@ -2662,7 +2686,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
*/
ret = pm_runtime_resume_and_get(wl->dev);
if (ret < 0)
- goto out_unlock;
+ goto out_deinit;
if (wl12xx_need_fw_change(wl, vif_count, true)) {
wl12xx_force_active_psm(wl);
@@ -2680,7 +2704,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
ret = wl1271_init_vif_specific(wl, vif);
if (ret < 0)
- goto out;
+ goto out_disable_role;
} else {
ret = wl12xx_cmd_role_enable(wl, vif->addr, WL1271_ROLE_DEVICE,
@@ -2691,7 +2715,7 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
/* needed mainly for configuring rate policies */
ret = wl1271_sta_hw_init(wl, wlvif);
if (ret < 0)
- goto out;
+ goto out_disable_role;
}
list_add(&wlvif->list, &wl->wlvif_list);
@@ -2701,8 +2725,18 @@ static int wl1271_op_add_interface(struct ieee80211_hw *hw,
wl->ap_count++;
else
wl->sta_count++;
+ goto out;
+
+out_disable_role:
+ if (!wlcore_is_p2p_mgmt(wlvif))
+ wl12xx_cmd_role_disable(wl, &wlvif->role_id);
+ else
+ wl12xx_cmd_role_disable(wl, &wlvif->dev_role_id);
out:
pm_runtime_put_autosuspend(wl->dev);
+out_deinit:
+ if (ret)
+ wl12xx_deinit_vif_data(wl, wlvif);
out_unlock:
mutex_unlock(&wl->mutex);
@@ -2714,7 +2748,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
bool reset_tx_queues)
{
struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif);
- int i, ret;
+ int ret;
bool is_ap = (wlvif->bss_type == BSS_TYPE_AP_BSS);
wl1271_debug(DEBUG_MAC80211, "mac80211 remove interface");
@@ -2789,23 +2823,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
/* clear all hlids (except system_hlid) */
wlvif->dev_hlid = WL12XX_INVALID_LINK_ID;
- if (wlvif->bss_type == BSS_TYPE_STA_BSS ||
- wlvif->bss_type == BSS_TYPE_IBSS) {
- wlvif->sta.hlid = WL12XX_INVALID_LINK_ID;
- wl12xx_free_rate_policy(wl, &wlvif->sta.basic_rate_idx);
- wl12xx_free_rate_policy(wl, &wlvif->sta.ap_rate_idx);
- wl12xx_free_rate_policy(wl, &wlvif->sta.p2p_rate_idx);
- wlcore_free_klv_template(wl, &wlvif->sta.klv_template_id);
- } else {
- wlvif->ap.bcast_hlid = WL12XX_INVALID_LINK_ID;
- wlvif->ap.global_hlid = WL12XX_INVALID_LINK_ID;
- wl12xx_free_rate_policy(wl, &wlvif->ap.mgmt_rate_idx);
- wl12xx_free_rate_policy(wl, &wlvif->ap.bcast_rate_idx);
- for (i = 0; i < CONF_TX_MAX_AC_COUNT; i++)
- wl12xx_free_rate_policy(wl,
- &wlvif->ap.ucast_rate_idx[i]);
- wl1271_free_ap_keys(wl, wlvif);
- }
+ wl12xx_deinit_vif_data(wl, wlvif);
dev_kfree_skb(wlvif->probereq);
wlvif->probereq = NULL;
--
2.34.1