Commit e9da68dd authored by Johannes Berg's avatar Johannes Berg

mac80211: allow hardware scan to fall back to software

In some cases, like in the rsi driver hardware scan offload, there
may be scenarios in which hardware scan might not be available or
desirable.

Allow drivers to cope with this by letting them fall back to software
scan by returning the special value 1 from the hardware scan method.
Requested-by: default avatarSushant Kumar Mishra <sushant2k1513@gmail.com>
Requested-by: default avatarSiva Rebbagondla <siva.rebbagondla@redpinesignals.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent c0a0189d
......@@ -3239,6 +3239,11 @@ enum ieee80211_reconfig_type {
* When the scan finishes, ieee80211_scan_completed() must be called;
* note that it also must be called when the scan cannot finish due to
* any error unless this callback returned a negative error code.
* This callback is also allowed to return the special return value 1,
* this indicates that hardware scan isn't desirable right now and a
* software scan should be done instead. A driver wishing to use this
* capability must ensure its (hardware) scan capabilities aren't
* advertised as more capable than mac80211's software scan is.
* The callback can sleep.
*
* @cancel_hw_scan: Ask the low-level tp cancel the active hw scan.
......
......@@ -356,7 +356,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
{
struct ieee80211_local *local = hw_to_local(hw);
bool hw_scan = local->ops->hw_scan;
bool hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
bool was_scanning = local->scanning;
struct cfg80211_scan_request *scan_req;
struct ieee80211_sub_if_data *scan_sdata;
......@@ -606,6 +606,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
struct cfg80211_scan_request *req)
{
struct ieee80211_local *local = sdata->local;
bool hw_scan = local->ops->hw_scan;
int rc;
lockdep_assert_held(&local->mtx);
......@@ -620,7 +621,8 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
return 0;
}
if (local->ops->hw_scan) {
again:
if (hw_scan) {
u8 *ies;
local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len;
......@@ -679,7 +681,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
else
memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN);
if (local->ops->hw_scan) {
if (hw_scan) {
__set_bit(SCAN_HW_SCANNING, &local->scanning);
} else if ((req->n_channels == 1) &&
(req->channels[0] == local->_oper_chandef.chan)) {
......@@ -722,7 +724,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
ieee80211_recalc_idle(local);
if (local->ops->hw_scan) {
if (hw_scan) {
WARN_ON(!ieee80211_prep_hw_scan(local));
rc = drv_hw_scan(local, sdata, local->hw_scan_req);
} else {
......@@ -740,6 +742,18 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
RCU_INIT_POINTER(local->scan_sdata, NULL);
}
if (hw_scan && rc == 1) {
/*
* we can't fall back to software for P2P-GO
* as it must update NoA etc.
*/
if (ieee80211_vif_type_p2p(&sdata->vif) ==
NL80211_IFTYPE_P2P_GO)
return -EOPNOTSUPP;
hw_scan = false;
goto again;
}
return rc;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment