bes2600: reset firmware state on wsm_join_confirm failure #12

Merged
marfrit merged 1 commits from bes2600/wsm-join-confirm-reset into cleanups 2026-05-21 08:45:22 +00:00
+43 -4
View File
@@ -2209,9 +2209,10 @@ void bes2600_join_work(struct work_struct *work)
struct wsm_template_frame probe_tmp = {
.frame_type = WSM_FRAME_TYPE_PROBE_REQUEST,
};
/*struct wsm_reset reset = {
.reset_statistics = true,
};*/
struct wsm_reset join_fail_reset = {
.reset_statistics = false,
};
bool join_failed = false;
BUG_ON(queueId >= 4);
@@ -2390,6 +2391,33 @@ void bes2600_join_work(struct work_struct *work)
#endif /*CONFIG_BES2600_TESTMODE*/
cancel_delayed_work_sync(&priv->join_timeout);
bes2600_pwr_clear_busy_event(priv->hw_priv, BES_PWR_LOCK_ON_JOIN);
/*
* Firmware rejected WSM_JOIN (wsm_join_confirm ret 1).
* Issue wsm_reset so the firmware returns to a clean
* IDLE state before the next association attempt.
*
* Without this reset the firmware sits in an
* intermediate post-reject state. A rapid second
* JOIN (e.g. wpa_supplicant retrying after the
* PREV_AUTH_NOT_VALID deauth that follows) hits an
* inconsistent firmware context, causing
* bes2600_sdio_read_rx_batch to return SDIO error
* which cascades into wifi_force_close.
*
* cw1200 ancestor (drivers/net/wireless/st/cw1200/
* sta.c:1339) queues unjoin_work on join failure for
* the same reason; bes2600_unjoin_work gates its
* wsm_reset on join_status != PASSIVE, so after a
* failed JOIN (join_status stays PASSIVE) that path
* never fires — call wsm_reset directly here instead.
*
* Contract: wsm_reset takes only wsm_cmd_lock; safe
* to call while conf_lock is held. wsm_oper_unlock
* was already called in wsm_join_confirm() before
* wsm_join() returned the error.
*/
WARN_ON(wsm_reset(hw_priv, &join_fail_reset, priv->if_id));
join_failed = true;
} else {
/* Upload keys */
#ifdef CONFIG_BES2600_TESTMODE
@@ -2414,7 +2442,18 @@ void bes2600_join_work(struct work_struct *work)
up(&hw_priv->conf_lock);
if (bss)
cfg80211_put_bss(hw_priv->hw->wiphy, bss);
wsm_unlock_tx(hw_priv);
/*
* On join failure: queue unjoin_work so the next association
* attempt is serialised after any lingering cleanup, matching
* cw1200 sta.c:1344 "Tx lock still held, unjoin will clear it."
* If unjoin_work is already queued, release TX immediately.
*/
if (join_failed) {
if (queue_work(hw_priv->workqueue, &priv->unjoin_work) <= 0)
wsm_unlock_tx(hw_priv);
} else {
wsm_unlock_tx(hw_priv);
}
}
void bes2600_join_timeout(struct work_struct *work)