3
0
mirror of https://git.kernel.org/pub/scm/network/wireless/iwd.git synced 2024-11-19 02:39:29 +01:00

scan: Handle CMD_SCAN_ABORTED during periodic scan, refactor

Also handle the case of a periodic scan when handling a
NL80211_CMD_SCAN_ABORTED.  The goal is to make sure the supplied callback
is always called if .trigger was called before, but this should also fix
some other corner cases.

 * I add a sp.triggered field for periodic scans since sc->state doesn't
   tell us whether the scan in progress was triggered by ourselved o
   someone else (in that case .trigger has not been called)

 * Since the NL80211_CMD_SCAN_ABORTED becomes similar to get_scan_done I
   move the common code to scan_finished

 * I believe this fixes a situation where we weren't updating sc->state
   if we'd not triggered the scan, because both get_scan_done and the
   NL80211_CMD_SCAN_ABORTED would return directly.
This commit is contained in:
Andrew Zaborowski 2017-03-14 16:11:34 +01:00 committed by Denis Kenzior
parent 5869b74c2e
commit c35225d239

View File

@ -56,6 +56,7 @@ struct scan_periodic {
void *userdata;
bool rearm:1;
bool retry:1;
bool triggered:1;
};
struct scan_request {
@ -474,6 +475,8 @@ static void scan_periodic_done(struct l_genl_msg *msg, void *user_data)
sc->state = SCAN_STATE_PASSIVE;
l_debug("Periodic scan triggered for ifindex: %u", sc->ifindex);
sc->sp.triggered = true;
if (sc->sp.trigger)
sc->sp.trigger(0, sc->sp.userdata);
}
@ -978,23 +981,15 @@ static void get_scan_callback(struct l_genl_msg *msg, void *user_data)
l_queue_insert(results->bss_list, bss, scan_bss_rank_compare, NULL);
}
static void get_scan_done(void *user)
static void scan_finished(struct scan_context *sc, uint32_t wiphy,
struct l_queue *bss_list)
{
struct scan_results *results = user;
struct scan_context *sc;
struct scan_request *sr;
scan_notify_func_t callback;
scan_notify_func_t callback = NULL;
void *userdata;
scan_destroy_func_t destroy;
scan_destroy_func_t destroy = NULL;
bool new_owner = false;
l_debug("get_scan_done");
sc = l_queue_find(scan_contexts, scan_context_match,
L_UINT_TO_PTR(results->ifindex));
if (!sc)
goto done;
sr = l_queue_peek_head(sc->requests);
if (sr && sr->triggered) {
callback = sr->callback;
@ -1004,15 +999,28 @@ static void get_scan_done(void *user)
scan_request_free(sr);
l_queue_pop_head(sc->requests);
} else if (sc->state == SCAN_STATE_PASSIVE && sc->sp.interval != 0) {
callback = sc->sp.callback;
userdata = sc->sp.userdata;
destroy = NULL;
} else
goto done;
/*
* If we'd called sc.sp->trigger, we must call back now
* independent of whether the scan was succesful or was
* aborted. If the scan was successful though we call back
* with the scan results even if didn't triggered this scan.
*/
if (sc->sp.triggered || bss_list) {
callback = sc->sp.callback;
userdata = sc->sp.userdata;
destroy = NULL;
}
if (callback)
new_owner = callback(results->wiphy, results->ifindex,
results->bss_list, userdata);
sc->sp.triggered = false;
}
if (callback) {
if (!bss_list)
bss_list = l_queue_new();
new_owner = callback(wiphy, sc->ifindex,
bss_list, userdata);
}
if (destroy)
destroy(userdata);
@ -1022,8 +1030,23 @@ static void get_scan_done(void *user)
if (!start_next_scan_request(sc) && sc->sp.rearm)
scan_periodic_rearm(sc);
done:
if (!new_owner)
if (bss_list && !new_owner)
l_queue_destroy(bss_list,
(l_queue_destroy_func_t) scan_bss_free);
}
static void get_scan_done(void *user)
{
struct scan_results *results = user;
struct scan_context *sc;
l_debug("get_scan_done");
sc = l_queue_find(scan_contexts, scan_context_match,
L_UINT_TO_PTR(results->ifindex));
if (sc)
scan_finished(sc, results->wiphy, results->bss_list);
else
l_queue_destroy(results->bss_list,
(l_queue_destroy_func_t) scan_bss_free);
@ -1150,38 +1173,10 @@ static void scan_notify(struct l_genl_msg *msg, void *user_data)
break;
case NL80211_CMD_SCAN_ABORTED:
{
struct scan_request *sr = l_queue_peek_head(sc->requests);
if (!sr || !sr->triggered) {
sc->state = SCAN_STATE_NOT_RUNNING;
break;
}
if (sr->callback) {
bool new_owner;
struct l_queue *bss_list = l_queue_new();
new_owner = sr->callback(attr_wiphy, attr_ifindex,
bss_list, sr->userdata);
if (!new_owner)
l_queue_destroy(bss_list, NULL);
}
if (sr->destroy)
sr->destroy(sr->userdata);
scan_request_free(sr);
l_queue_pop_head(sc->requests);
sc->state = SCAN_STATE_NOT_RUNNING;
if (!start_next_scan_request(sc) && sc->sp.rearm)
scan_periodic_rearm(sc);
scan_finished(sc, attr_wiphy, NULL);
break;
}
}
}
uint8_t scan_freq_to_channel(uint32_t freq, enum scan_band *out_band)