aff632ea64
On a BES2600-based PineTab2, mac80211's background-scan cadence
(about every 30 s when associated) triggers a two-step WARN splat
pattern, visible in dmesg roughly 30 times per 10 min of regular
WiFi use:
wsm_generic_confirm ret 2
WARNING: at wsm_handle_rx+0x8a4/0xf30 [bes2600]
... full stack trace ...
ieee80211 phy0: wsm_generic_confirm failed for request 0x0007.
WARNING: at bes2600_scan_work+0x5d4/0x810 [bes2600]
... full stack trace ...
ieee80211 phy0: [SCAN] Scan failed (-22).
0x0007 is the WSM start-scan request; status 2 is the firmware's
rejected-by-policy response, which it returns for at least two
conditions:
a) BT A2DP streaming in non-FDD coex mode -- the coex arbiter
in firmware won't grant an off-channel window while a SCO/
A2DP link is queued.
b) A firmware-internal busy state whose exact trigger the
driver cannot observe directly (confirmed on ohm with BT
disconnected -- rejection still fires). Likely transient
firmware-PM transitions.
Both are protocol-level policy responses, not kernel bugs, so the
full stack-trace WARN treatment is counterproductive: it buries
real problems and gets new users convinced the driver is broken.
Three-part fix:
1. struct bes2600_scan grows two fields -- reject_count and
backoff_until -- zero-initialised via the existing
ieee80211_alloc_hw()-provided kzalloc.
2. bes2600_scan_work() now consults bes2600_scan_should_defer()
before calling bes2600_scan_start(). The helper short-
circuits in two cases:
- coex_is_bt_a2dp() is true and coex is not in FDD mode,
since we already know the firmware will reject;
- BES2600_SCAN_REJECT_THRESHOLD (3) consecutive rejections
have fired and the BES2600_SCAN_BACKOFF_JIFFIES (10 s)
backoff window has not yet elapsed.
On defer or on a real firmware rejection, reject_count is
bumped and backoff_until is refreshed. A successful scan
clears reject_count.
3. The WARN_ON(hw_priv->scan.status) at the scan_start() call
site is replaced with a plain branch into the existing
fail: label. wsm_generic_confirm()'s WARN() becomes a
bes_devel() -- the per-request wiphy_warn in wsm_handle_rx
(which includes the offending request id) is kept, so real
debugging information is still on tape.
Net behaviour:
- Expected rejections no longer produce stack traces. The only
log line that remains on a rejected background scan is the
upstream-caller's wiphy_warn identifying request 0x0007 or
equivalent.
- The driver stops hammering the firmware with doomed scan
requests -- 3 rejections trigger a 10 s pause, during which
bes2600_scan_work() returns without issuing WSM 0x0007.
- The scan-completion path is unchanged; mac80211 sees the
scan complete with no results and reissues on its normal
cadence.
- Real protocol-layer bugs (unexpected underflow in the
confirm buffer) still WARN_ON at the 'underflow:' label.
Verified on ohm (PineTab2, linux-pinetab2 6.19.10-danctnix1-1):
WARN splat count dropped from 32 to 0 per 10 min uptime. WiFi
stays associated. No regression in other counters (KFENCE,
sdio_tx_work, RX failure, PS Mode Error, factory cali fail all
remain 0).
Signed-off-by: Markus Fritsche <fritsche.markus@gmail.com>
84 lines
2.6 KiB
C
84 lines
2.6 KiB
C
/*
|
|
* Scan interface for BES2600 mac80211 drivers
|
|
*
|
|
* Copyright (c) 2010, Bestechnic
|
|
* Author:
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*/
|
|
|
|
#ifndef SCAN_H_INCLUDED
|
|
#define SCAN_H_INCLUDED
|
|
|
|
#include <linux/semaphore.h>
|
|
#include "wsm.h"
|
|
|
|
/* external */ struct sk_buff;
|
|
/* external */ struct cfg80211_scan_request;
|
|
/* external */ struct ieee80211_channel;
|
|
/* external */ struct ieee80211_hw;
|
|
/* external */ struct work_struct;
|
|
|
|
struct bes2600_scan {
|
|
struct semaphore lock;
|
|
struct work_struct work;
|
|
#ifdef ROAM_OFFLOAD
|
|
struct work_struct swork; /* scheduled scan work */
|
|
struct cfg80211_sched_scan_request *sched_req;
|
|
#endif /*ROAM_OFFLOAD*/
|
|
struct delayed_work timeout;
|
|
struct cfg80211_scan_request *req;
|
|
struct ieee80211_channel **begin;
|
|
struct ieee80211_channel **curr;
|
|
struct ieee80211_channel **end;
|
|
struct wsm_ssid ssids[WSM_SCAN_MAX_NUM_OF_SSIDS];
|
|
int output_power;
|
|
int n_ssids;
|
|
int status;
|
|
atomic_t in_progress;
|
|
/* Direct probe requests workaround */
|
|
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,
|
|
struct ieee80211_vif *vif,
|
|
struct ieee80211_scan_request *hw_req);
|
|
#ifdef ROAM_OFFLOAD
|
|
int bes2600_hw_sched_scan_start(struct ieee80211_hw *hw,
|
|
struct ieee80211_vif *vif,
|
|
struct cfg80211_sched_scan_request *req,
|
|
struct ieee80211_sched_scan_ies *ies);
|
|
void bes2600_hw_sched_scan_stop(struct bes2600_common *priv);
|
|
void bes2600_sched_scan_work(struct work_struct *work);
|
|
#endif /*ROAM_OFFLOAD*/
|
|
void bes2600_scan_work(struct work_struct *work);
|
|
void bes2600_scan_timeout(struct work_struct *work);
|
|
void bes2600_scan_complete_cb(struct bes2600_common *priv,
|
|
struct wsm_scan_complete *arg);
|
|
void bes2600_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
|
|
|
|
/* ******************************************************************** */
|
|
/* Raw probe requests TX workaround */
|
|
void bes2600_probe_work(struct work_struct *work);
|
|
#ifdef CONFIG_BES2600_TESTMODE
|
|
/* Advance Scan Timer */
|
|
void bes2600_advance_scan_timeout(struct work_struct *work);
|
|
#endif
|
|
|
|
#endif
|