diff --git a/bes2600/scan.c b/bes2600/scan.c index b2c22e7..faa1c90 100644 --- a/bes2600/scan.c +++ b/bes2600/scan.c @@ -14,11 +14,50 @@ #include "scan.h" #include "sta.h" #include "pm.h" +#include "epta_coex.h" #include "epta_request.h" #include "bes_pwr.h" +/* + * After this many consecutive WSM scan rejections from firmware, stop + * issuing new scans for BES2600_SCAN_BACKOFF_JIFFIES and let the state + * that's rejecting them (coex window, firmware-internal busy) clear. + */ +#define BES2600_SCAN_REJECT_THRESHOLD 3 +#define BES2600_SCAN_BACKOFF_JIFFIES (10 * HZ) + static void bes2600_scan_restart_delayed(struct bes2600_vif *priv); +/* + * Decide whether to skip sending the next WSM scan command without + * bothering the firmware. Two triggers: + * + * 1. BT A2DP is streaming in non-FDD coex mode. The firmware is + * known to reject scan requests during that window; short- + * circuiting here saves a WSM round-trip and avoids the + * wsm_generic_confirm / scan_work warning cascade that follows. + * + * 2. We already saw >= BES2600_SCAN_REJECT_THRESHOLD consecutive + * rejections on recent scan attempts and the backoff window has + * not yet elapsed. Whatever was rejecting them is likely still + * rejecting them; give it time. + * + * Returns true if the caller should abandon the scan iteration. + */ +static bool bes2600_scan_should_defer(struct bes2600_common *hw_priv) +{ +#ifdef WIFI_BT_COEXIST_EPTA_ENABLE + if (!coex_is_fdd_mode() && coex_is_bt_a2dp()) + return true; +#endif + + if (hw_priv->scan.reject_count >= BES2600_SCAN_REJECT_THRESHOLD && + time_before(jiffies, hw_priv->scan.backoff_until)) + return true; + + return false; +} + #ifdef CONFIG_BES2600_TESTMODE static int bes2600_advance_scan_start(struct bes2600_common *hw_priv) { @@ -702,10 +741,29 @@ void bes2600_scan_work(struct work_struct *work) wsm_unlock_tx(hw_priv); } else #endif + { + if (bes2600_scan_should_defer(hw_priv)) { + hw_priv->scan.status = -EBUSY; + hw_priv->scan.reject_count++; + hw_priv->scan.backoff_until = + jiffies + BES2600_SCAN_BACKOFF_JIFFIES; + wiphy_dbg(priv->hw->wiphy, + "[SCAN] deferred (coex/backoff, reject_count=%u)\n", + hw_priv->scan.reject_count); + kfree(scan.ch); + goto fail; + } hw_priv->scan.status = bes2600_scan_start(priv, &scan); + } kfree(scan.ch); - if (WARN_ON(hw_priv->scan.status)) + if (hw_priv->scan.status) { + hw_priv->scan.reject_count++; + hw_priv->scan.backoff_until = + jiffies + BES2600_SCAN_BACKOFF_JIFFIES; + /* Lower callers already logged the reason at wiphy_warn. */ goto fail; + } + hw_priv->scan.reject_count = 0; hw_priv->scan.curr = it; } up(&hw_priv->conf_lock); diff --git a/bes2600/scan.h b/bes2600/scan.h index e50fa36..1f3adea 100644 --- a/bes2600/scan.h +++ b/bes2600/scan.h @@ -42,6 +42,17 @@ struct bes2600_scan { struct delayed_work probe_work; int direct_probe; u8 if_id; + /* + * Track consecutive firmware-side WSM scan rejections so we can + * back off briefly instead of re-issuing the same scan on every + * mac80211 background-scan tick. Firmware returns WSM status != 0 + * for a handful of transient conditions (BT A2DP active in non- + * FDD coex, firmware-internal busy windows) and keeps rejecting + * until the state clears; retrying at full cadence just floods + * dmesg. + */ + unsigned int reject_count; + unsigned long backoff_until; }; int bes2600_hw_scan(struct ieee80211_hw *hw, diff --git a/bes2600/wsm.c b/bes2600/wsm.c index d40df30..55a4e2b 100644 --- a/bes2600/wsm.c +++ b/bes2600/wsm.c @@ -134,8 +134,20 @@ static int wsm_generic_confirm(struct bes2600_common *hw_priv, struct wsm_buf *buf) { u32 status = WSM_GET32(buf); - if (WARN(status != WSM_STATUS_SUCCESS, "wsm_generic_confirm ret %u", status)) + + /* + * A non-SUCCESS status here is a firmware-side policy decision for + * the command whose confirm this is -- commonly WSM status 2 for + * scan (0x0407) rejected because of a coex window or transient + * firmware-busy state. It is not a driver/kernel bug, so avoid the + * WARN()/stack-trace treatment; the caller already emits a + * wiphy_warn identifying the request id and will propagate the + * error to mac80211. + */ + if (status != WSM_STATUS_SUCCESS) { + bes_devel("%s ret %u\n", __func__, status); return -EINVAL; + } return 0; underflow: