mirror of
https://git.freebsd.org/src.git
synced 2026-01-16 23:02:24 +00:00
LinuxKPI: 802.11: improve scan handling
Under certain circumstances a hw_scan may be downgraded to a software scan. Handle these situations better and make sure we free resources in all cases once. [1] Also leave a note about scanning all bands (or we would have to switch bands manually). In both cases hardware doing and driver saying seem not entirely consistent for all and all firmware. Sponsored by: The FreeBSD Foundation MFC after: 10 days Reported by: imp [1]
This commit is contained in:
parent
4e8d558c9d
commit
3206587a20
2 changed files with 72 additions and 21 deletions
|
|
@ -2669,12 +2669,7 @@ sw_scan:
|
|||
int band, i, ssid_count, common_ie_len;
|
||||
uint32_t band_mask;
|
||||
uint8_t *ie, *ieend;
|
||||
|
||||
if (!ieee80211_hw_check(hw, SINGLE_SCAN_ON_ALL_BANDS)) {
|
||||
IMPROVE("individual band scans not yet supported");
|
||||
/* In theory net80211 would have to drive this. */
|
||||
return;
|
||||
}
|
||||
bool running;
|
||||
|
||||
ssid_count = min(ss->ss_nssid, hw->wiphy->max_scan_ssids);
|
||||
ssids_len = ssid_count * sizeof(*ssids);
|
||||
|
|
@ -2688,6 +2683,18 @@ sw_scan:
|
|||
ss->ss_chans[ss->ss_next + i]);
|
||||
band_mask |= (1 << band);
|
||||
}
|
||||
|
||||
if (!ieee80211_hw_check(hw, SINGLE_SCAN_ON_ALL_BANDS)) {
|
||||
IMPROVE("individual band scans not yet supported, only scanning first band");
|
||||
/* In theory net80211 should drive this. */
|
||||
/* Probably we need to add local logic for now;
|
||||
* need to deal with scan_complete
|
||||
* and cancel_scan and keep local state.
|
||||
* Also cut the nchan down above.
|
||||
*/
|
||||
/* XXX-BZ ath10k does not set this but still does it? &$%^ */
|
||||
}
|
||||
|
||||
chan_len = nchan * (sizeof(lc) + sizeof(*lc));
|
||||
|
||||
common_ie_len = 0;
|
||||
|
|
@ -2704,10 +2711,7 @@ sw_scan:
|
|||
common_ie_len, hw->wiphy->max_scan_ie_len);
|
||||
}
|
||||
|
||||
KASSERT(lhw->hw_req == NULL, ("%s: ic %p lhw %p hw_req %p "
|
||||
"!= NULL\n", __func__, ic, lhw, lhw->hw_req));
|
||||
|
||||
lhw->hw_req = hw_req = malloc(sizeof(*hw_req) + ssids_len +
|
||||
hw_req = malloc(sizeof(*hw_req) + ssids_len +
|
||||
s6ghzlen + chan_len + lhw->supbands * lhw->scan_ie_len +
|
||||
common_ie_len, M_LKPI80211, M_WAITOK | M_ZERO);
|
||||
|
||||
|
|
@ -2737,7 +2741,7 @@ sw_scan:
|
|||
c = ss->ss_chans[ss->ss_next + i];
|
||||
|
||||
lc->hw_value = c->ic_ieee;
|
||||
lc->center_freq = c->ic_freq;
|
||||
lc->center_freq = c->ic_freq; /* XXX */
|
||||
/* lc->flags */
|
||||
lc->band = lkpi_net80211_chan_to_nl80211_band(c);
|
||||
lc->max_power = c->ic_maxpower;
|
||||
|
|
@ -2774,12 +2778,48 @@ sw_scan:
|
|||
|
||||
lvif = VAP_TO_LVIF(vap);
|
||||
vif = LVIF_TO_VIF(lvif);
|
||||
|
||||
LKPI_80211_LHW_SCAN_LOCK(lhw);
|
||||
/* Re-check under lock. */
|
||||
running = (lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0;
|
||||
if (!running) {
|
||||
KASSERT(lhw->hw_req == NULL, ("%s: ic %p lhw %p hw_req %p "
|
||||
"!= NULL\n", __func__, ic, lhw, lhw->hw_req));
|
||||
|
||||
lhw->scan_flags |= LKPI_LHW_SCAN_RUNNING;
|
||||
lhw->hw_req = hw_req;
|
||||
}
|
||||
LKPI_80211_LHW_SCAN_UNLOCK(lhw);
|
||||
if (running) {
|
||||
free(hw_req, M_LKPI80211);
|
||||
return;
|
||||
}
|
||||
|
||||
error = lkpi_80211_mo_hw_scan(hw, vif, hw_req);
|
||||
if (error != 0) {
|
||||
ieee80211_cancel_scan(vap);
|
||||
|
||||
free(hw_req, M_LKPI80211);
|
||||
lhw->hw_req = NULL;
|
||||
/*
|
||||
* ieee80211_scan_completed must be called in either
|
||||
* case of error or none. So let the free happen there
|
||||
* and only there.
|
||||
* That would be fine in theory but in practice drivers
|
||||
* behave differently:
|
||||
* ath10k does not return hw_scan until after scan_complete
|
||||
* and can then still return an error.
|
||||
* rtw88 can return 1 or -EBUSY without scan_complete
|
||||
* iwlwifi can return various errors before scan starts
|
||||
* ...
|
||||
* So we cannot rely on that behaviour and have to check
|
||||
* and balance between both code paths.
|
||||
*/
|
||||
LKPI_80211_LHW_SCAN_LOCK(lhw);
|
||||
if ((lhw->scan_flags & LKPI_LHW_SCAN_RUNNING) != 0) {
|
||||
free(lhw->hw_req, M_LKPI80211);
|
||||
lhw->hw_req = NULL;
|
||||
lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
|
||||
}
|
||||
LKPI_80211_LHW_SCAN_UNLOCK(lhw);
|
||||
|
||||
/*
|
||||
* XXX-SIGH magic number.
|
||||
|
|
@ -2790,6 +2830,12 @@ sw_scan:
|
|||
LKPI_80211_LHW_SCAN_LOCK(lhw);
|
||||
lhw->scan_flags &= ~LKPI_LHW_SCAN_HW;
|
||||
LKPI_80211_LHW_SCAN_UNLOCK(lhw);
|
||||
/*
|
||||
* XXX If we clear this now and later a driver
|
||||
* thinks it * can do a hw_scan again, we will
|
||||
* currently not re-enable it?
|
||||
*/
|
||||
vap->iv_flags_ext &= ~IEEE80211_FEXT_SCAN_OFFLOAD;
|
||||
ieee80211_start_scan(vap,
|
||||
IEEE80211_SCAN_ACTIVE |
|
||||
IEEE80211_SCAN_NOPICK |
|
||||
|
|
|
|||
|
|
@ -43,8 +43,9 @@ __FBSDID("$FreeBSD$");
|
|||
#ifdef LINUXKPI_DEBUG_80211
|
||||
#define LKPI_80211_TRACE_MO(fmt, ...) \
|
||||
if (linuxkpi_debug_80211 & D80211_TRACE_MO) \
|
||||
printf("LKPI_80211_TRACE_MO %s:%d:_" fmt "\n", \
|
||||
__func__, __LINE__, __VA_ARGS__)
|
||||
printf("LKPI_80211_TRACE_MO %s:%d: %d %d %u_" fmt "\n", \
|
||||
__func__, __LINE__, curcpu, curthread->td_tid, \
|
||||
(unsigned int)ticks, __VA_ARGS__)
|
||||
#else
|
||||
#define LKPI_80211_TRACE_MO(...) do { } while(0)
|
||||
#endif
|
||||
|
|
@ -215,18 +216,22 @@ lkpi_80211_mo_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
|
|||
struct lkpi_hw *lhw;
|
||||
int error;
|
||||
|
||||
/*
|
||||
* MUST NOT return EPERM as that is a "magic number 1" based on rtw88
|
||||
* driver indicating hw_scan is not supported despite the ops call
|
||||
* being available.
|
||||
*/
|
||||
|
||||
lhw = HW_TO_LHW(hw);
|
||||
if (lhw->ops->hw_scan == NULL) {
|
||||
/* XXX-BZ can we hide other scans like we can for sta_add..? */
|
||||
error = EOPNOTSUPP;
|
||||
/* Return magic number to use sw scan. */
|
||||
error = 1;
|
||||
goto out;
|
||||
}
|
||||
|
||||
lhw->scan_flags |= LKPI_LHW_SCAN_RUNNING;
|
||||
LKPI_80211_TRACE_MO("hw %p vif %p sr %p", hw, vif, sr);
|
||||
LKPI_80211_TRACE_MO("CALLING hw %p vif %p sr %p", hw, vif, sr);
|
||||
error = lhw->ops->hw_scan(hw, vif, sr);
|
||||
if (error != 0)
|
||||
lhw->scan_flags &= ~LKPI_LHW_SCAN_RUNNING;
|
||||
LKPI_80211_TRACE_MO("RETURNING hw %p vif %p sr %p error %d", hw, vif, sr, error);
|
||||
|
||||
out:
|
||||
return (error);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue