diff options
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 4 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 6 | ||||
-rw-r--r-- | net/mac80211/iface.c | 3 | ||||
-rw-r--r-- | net/mac80211/mesh_hwmp.c | 5 | ||||
-rw-r--r-- | net/mac80211/mesh_pathtbl.c | 2 | ||||
-rw-r--r-- | net/mac80211/mesh_sync.c | 32 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 35 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel.c | 13 | ||||
-rw-r--r-- | net/mac80211/rc80211_minstrel_ht.c | 5 | ||||
-rw-r--r-- | net/mac80211/scan.c | 43 | ||||
-rw-r--r-- | net/mac80211/status.c | 8 | ||||
-rw-r--r-- | net/mac80211/tx.c | 4 | ||||
-rw-r--r-- | net/mac80211/util.c | 42 | ||||
-rw-r--r-- | net/mac80211/work.c | 15 |
14 files changed, 136 insertions, 81 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 355735491252..510a745c3108 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -2688,10 +2688,12 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev, } static struct ieee80211_channel * -ieee80211_wiphy_get_channel(struct wiphy *wiphy) +ieee80211_wiphy_get_channel(struct wiphy *wiphy, + enum nl80211_channel_type *type) { struct ieee80211_local *local = wiphy_priv(wiphy); + *type = local->_oper_channel_type; return local->oper_channel; } diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 4be11ea3dfc4..bd7a451b0849 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1260,6 +1260,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req); void ieee80211_scan_cancel(struct ieee80211_local *local); +void ieee80211_run_deferred_scan(struct ieee80211_local *local); ieee80211_rx_result ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb); @@ -1272,9 +1273,6 @@ ieee80211_bss_info_update(struct ieee80211_local *local, struct ieee802_11_elems *elems, struct ieee80211_channel *channel, bool beacon); -struct ieee80211_bss * -ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len); void ieee80211_rx_bss_put(struct ieee80211_local *local, struct ieee80211_bss *bss); @@ -1403,7 +1401,7 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) extern void *mac80211_wiphy_privid; /* for wiphy privid */ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, enum nl80211_iftype type); -int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, +int ieee80211_frame_duration(enum ieee80211_band band, size_t len, int rate, int erp, int short_preamble); void mac80211_ev_michael_mic_failure(struct ieee80211_sub_if_data *sdata, int keyidx, struct ieee80211_hdr *hdr, const u8 *tsc, diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 6e85faed053d..23d1da376eb3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -163,7 +163,8 @@ static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata) return -EINVAL; } - if (sdata->vif.type != NL80211_IFTYPE_AP) { + if ((sdata->vif.type != NL80211_IFTYPE_AP) || + !(sdata->local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)) { sdata->vif.cab_queue = IEEE80211_INVAL_HW_QUEUE; return 0; } diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index a80da3784a25..503016f58631 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c @@ -800,10 +800,11 @@ static void hwmp_rann_frame_process(struct ieee80211_sub_if_data *sdata, 0, sdata); mpath->sn = orig_sn; mpath->rann_metric = metric + metric_txsta; + /* Recording RANNs sender address to send individually + * addressed PREQs destined for root mesh STA */ + memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN); } - /* Using individually addressed PREQ for root node */ - memcpy(mpath->rann_snd_addr, mgmt->sa, ETH_ALEN); mpath->is_root = true; if (root_is_gate) diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 49aaefd99635..baa6096c66b4 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c @@ -538,6 +538,8 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) read_lock_bh(&pathtbl_resize_lock); memcpy(new_mpath->dst, dst, ETH_ALEN); + memset(new_mpath->rann_snd_addr, 0xff, ETH_ALEN); + new_mpath->is_root = false; new_mpath->sdata = sdata; new_mpath->flags = 0; skb_queue_head_init(&new_mpath->frame_queue); diff --git a/net/mac80211/mesh_sync.c b/net/mac80211/mesh_sync.c index f78b0139856f..ff60d6bcc631 100644 --- a/net/mac80211/mesh_sync.c +++ b/net/mac80211/mesh_sync.c @@ -22,7 +22,20 @@ /* This is not in the standard. It represents a tolerable tbtt drift below * which we do no TSF adjustment. */ -#define TBTT_MINIMUM_ADJUSTMENT 10 +#define TOFFSET_MINIMUM_ADJUSTMENT 10 + +/* This is not in the standard. It is a margin added to the + * Toffset setpoint to mitigate TSF overcorrection + * introduced by TSF adjustment latency. + */ +#define TOFFSET_SET_MARGIN 20 + +/* This is not in the standard. It represents the maximum Toffset jump above + * which we'll invalidate the Toffset setpoint and choose a new setpoint. This + * could be, for instance, in case a neighbor is restarted and its TSF counter + * reset. + */ +#define TOFFSET_MAXIMUM_ADJUSTMENT 30000 /* 30 ms */ struct sync_method { u8 method; @@ -156,15 +169,22 @@ static void mesh_sync_offset_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { s64 t_clockdrift = sta->t_offset_setpoint - sta->t_offset; - - msync_dbg("STA %pM : sta->t_offset=%lld," - " sta->t_offset_setpoint=%lld," - " t_clockdrift=%lld", + msync_dbg("STA %pM : sta->t_offset=%lld, sta->t_offset_setpoint=%lld, t_clockdrift=%lld", sta->sta.addr, (long long) sta->t_offset, (long long) sta->t_offset_setpoint, (long long) t_clockdrift); + + if (t_clockdrift > TOFFSET_MAXIMUM_ADJUSTMENT || + t_clockdrift < -TOFFSET_MAXIMUM_ADJUSTMENT) { + msync_dbg("STA %pM : t_clockdrift=%lld too large, setpoint reset", + sta->sta.addr, + (long long) t_clockdrift); + clear_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN); + goto no_sync; + } + rcu_read_unlock(); spin_lock_bh(&ifmsh->sync_offset_lock); @@ -200,7 +220,7 @@ static void mesh_sync_offset_adjust_tbtt(struct ieee80211_sub_if_data *sdata) spin_lock_bh(&ifmsh->sync_offset_lock); if (ifmsh->sync_offset_clockdrift_max > - TBTT_MINIMUM_ADJUSTMENT) { + TOFFSET_MINIMUM_ADJUSTMENT) { /* Since ajusting the tsf here would * require a possibly blocking call * to the driver tsf setter, we punt diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index bbf1100d90d6..c8836fa7d627 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1447,19 +1447,24 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) { struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + struct ieee80211_local *local = sdata->local; + mutex_lock(&local->mtx); if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL | - IEEE80211_STA_CONNECTION_POLL))) - return; + IEEE80211_STA_CONNECTION_POLL))) { + mutex_unlock(&local->mtx); + return; + } ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | IEEE80211_STA_BEACON_POLL); - mutex_lock(&sdata->local->iflist_mtx); - ieee80211_recalc_ps(sdata->local, -1); - mutex_unlock(&sdata->local->iflist_mtx); + + mutex_lock(&local->iflist_mtx); + ieee80211_recalc_ps(local, -1); + mutex_unlock(&local->iflist_mtx); if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) - return; + goto out; /* * We've received a probe response, but are not sure whether @@ -1471,6 +1476,9 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata) mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); +out: + ieee80211_run_deferred_scan(local); + mutex_unlock(&local->mtx); } void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, @@ -1546,17 +1554,18 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, if (!ieee80211_sdata_running(sdata)) return; - if (sdata->local->scanning) - return; - - if (sdata->local->tmp_channel) - return; - mutex_lock(&ifmgd->mtx); if (!ifmgd->associated) goto out; + mutex_lock(&sdata->local->mtx); + + if (sdata->local->tmp_channel || sdata->local->scanning) { + mutex_unlock(&sdata->local->mtx); + goto out; + } + #ifdef CONFIG_MAC80211_VERBOSE_DEBUG if (beacon && net_ratelimit()) printk(KERN_DEBUG "%s: detected beacon loss from AP " @@ -1583,6 +1592,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata, else ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL; + mutex_unlock(&sdata->local->mtx); + if (already) goto out; diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index b39dda523f39..79633ae06fd6 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c @@ -334,14 +334,15 @@ minstrel_get_rate(void *priv, struct ieee80211_sta *sta, static void -calc_rate_durations(struct ieee80211_local *local, struct minstrel_rate *d, +calc_rate_durations(enum ieee80211_band band, + struct minstrel_rate *d, struct ieee80211_rate *rate) { int erp = !!(rate->flags & IEEE80211_RATE_ERP_G); - d->perfect_tx_time = ieee80211_frame_duration(local, 1200, + d->perfect_tx_time = ieee80211_frame_duration(band, 1200, rate->bitrate, erp, 1); - d->ack_time = ieee80211_frame_duration(local, 10, + d->ack_time = ieee80211_frame_duration(band, 10, rate->bitrate, erp, 1); } @@ -379,14 +380,14 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, { struct minstrel_sta_info *mi = priv_sta; struct minstrel_priv *mp = priv; - struct ieee80211_local *local = hw_to_local(mp->hw); struct ieee80211_rate *ctl_rate; unsigned int i, n = 0; unsigned int t_slot = 9; /* FIXME: get real slot time */ mi->lowest_rix = rate_lowest_index(sband, sta); ctl_rate = &sband->bitrates[mi->lowest_rix]; - mi->sp_ack_dur = ieee80211_frame_duration(local, 10, ctl_rate->bitrate, + mi->sp_ack_dur = ieee80211_frame_duration(sband->band, 10, + ctl_rate->bitrate, !!(ctl_rate->flags & IEEE80211_RATE_ERP_G), 1); for (i = 0; i < sband->n_bitrates; i++) { @@ -402,7 +403,7 @@ minstrel_rate_init(void *priv, struct ieee80211_supported_band *sband, mr->rix = i; mr->bitrate = sband->bitrates[i].bitrate / 5; - calc_rate_durations(local, mr, &sband->bitrates[i]); + calc_rate_durations(sband->band, mr, &sband->bitrates[i]); /* calculate maximum number of retransmissions before * fallback (based on maximum segment size) */ diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 3b3dcae13bbc..2d1acc6c5445 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c @@ -692,7 +692,6 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, struct minstrel_ht_sta_priv *msp = priv_sta; struct minstrel_ht_sta *mi = &msp->ht; struct ieee80211_mcs_info *mcs = &sta->ht_cap.mcs; - struct ieee80211_local *local = hw_to_local(mp->hw); u16 sta_cap = sta->ht_cap.cap; int n_supported = 0; int ack_dur; @@ -711,8 +710,8 @@ minstrel_ht_update_caps(void *priv, struct ieee80211_supported_band *sband, memset(mi, 0, sizeof(*mi)); mi->stats_update = jiffies; - ack_dur = ieee80211_frame_duration(local, 10, 60, 1, 1); - mi->overhead = ieee80211_frame_duration(local, 0, 60, 1, 1) + ack_dur; + ack_dur = ieee80211_frame_duration(sband->band, 10, 60, 1, 1); + mi->overhead = ieee80211_frame_duration(sband->band, 0, 60, 1, 1) + ack_dur; mi->overhead_rtscts = mi->overhead + 2 * ack_dur; mi->avg_ampdu_len = MINSTREL_FRAC(1, 1); diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index c70e17677135..45f5aa229efd 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -29,20 +29,6 @@ #define IEEE80211_CHANNEL_TIME (HZ / 33) #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8) -struct ieee80211_bss * -ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, - u8 *ssid, u8 ssid_len) -{ - struct cfg80211_bss *cbss; - - cbss = cfg80211_get_bss(local->hw.wiphy, - ieee80211_get_channel(local->hw.wiphy, freq), - bssid, ssid, ssid_len, 0, 0); - if (!cbss) - return NULL; - return (void *)cbss->priv; -} - static void ieee80211_rx_bss_free(struct cfg80211_bss *cbss) { struct ieee80211_bss *bss = (void *)cbss->priv; @@ -387,6 +373,33 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) return 0; } +static bool ieee80211_can_scan(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata) +{ + if (!list_empty(&local->work_list)) + return false; + + if (sdata->vif.type == NL80211_IFTYPE_STATION && + sdata->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | + IEEE80211_STA_CONNECTION_POLL)) + return false; + + return true; +} + +void ieee80211_run_deferred_scan(struct ieee80211_local *local) +{ + lockdep_assert_held(&local->mtx); + + if (!local->scan_req || local->scanning) + return; + + if (!ieee80211_can_scan(local, local->scan_sdata)) + return; + + ieee80211_queue_delayed_work(&local->hw, &local->scan_work, + round_jiffies_relative(0)); +} static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, struct cfg80211_scan_request *req) @@ -399,7 +412,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, if (local->scan_req) return -EBUSY; - if (!list_empty(&local->work_list)) { + if (!ieee80211_can_scan(local, sdata)) { /* wait for the work to finish/time out */ local->scan_req = req; local->scan_sdata = sdata; diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 5f8f89e89d6b..05f257aa2e08 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c @@ -355,7 +355,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) int rtap_len; for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { - if (info->status.rates[i].idx < 0) { + if ((info->flags & IEEE80211_TX_CTL_AMPDU) && + !(info->flags & IEEE80211_TX_STAT_AMPDU)) { + /* just the first aggr frame carry status info */ + info->status.rates[i].idx = -1; + info->status.rates[i].count = 0; + break; + } else if (info->status.rates[i].idx < 0) { break; } else if (i >= hw->max_report_rates) { /* the HW cannot have attempted that rate */ diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4f6aac16ac3a..0abbef952c14 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -159,7 +159,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, /* Time needed to transmit ACK * (10 bytes + 4-byte FCS = 112 bits) plus SIFS; rounded up * to closest integer */ - dur = ieee80211_frame_duration(local, 10, rate, erp, + dur = ieee80211_frame_duration(sband->band, 10, rate, erp, tx->sdata->vif.bss_conf.use_short_preamble); if (next_frag_len) { @@ -167,7 +167,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, * transmit next fragment plus ACK and 2 x SIFS. */ dur *= 2; /* ACK + SIFS */ /* next fragment */ - dur += ieee80211_frame_duration(local, next_frag_len, + dur += ieee80211_frame_duration(sband->band, next_frag_len, txrate->bitrate, erp, tx->sdata->vif.bss_conf.use_short_preamble); } diff --git a/net/mac80211/util.c b/net/mac80211/util.c index e67fe5c1def9..89c1e5b9ba94 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -106,7 +106,7 @@ void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) } } -int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, +int ieee80211_frame_duration(enum ieee80211_band band, size_t len, int rate, int erp, int short_preamble) { int dur; @@ -120,7 +120,7 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, * DIV_ROUND_UP() operations. */ - if (local->hw.conf.channel->band == IEEE80211_BAND_5GHZ || erp) { + if (band == IEEE80211_BAND_5GHZ || erp) { /* * OFDM: * @@ -162,10 +162,10 @@ int ieee80211_frame_duration(struct ieee80211_local *local, size_t len, /* Exported duration function for driver use */ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, struct ieee80211_vif *vif, + enum ieee80211_band band, size_t frame_len, struct ieee80211_rate *rate) { - struct ieee80211_local *local = hw_to_local(hw); struct ieee80211_sub_if_data *sdata; u16 dur; int erp; @@ -179,7 +179,7 @@ __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw, erp = rate->flags & IEEE80211_RATE_ERP_G; } - dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, erp, + dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp, short_preamble); return cpu_to_le16(dur); @@ -198,7 +198,7 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, u16 dur; struct ieee80211_supported_band *sband; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = local->hw.wiphy->bands[frame_txctl->band]; short_preamble = false; @@ -213,13 +213,13 @@ __le16 ieee80211_rts_duration(struct ieee80211_hw *hw, } /* CTS duration */ - dur = ieee80211_frame_duration(local, 10, rate->bitrate, + dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate, erp, short_preamble); /* Data frame duration */ - dur += ieee80211_frame_duration(local, frame_len, rate->bitrate, + dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, erp, short_preamble); /* ACK duration */ - dur += ieee80211_frame_duration(local, 10, rate->bitrate, + dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, erp, short_preamble); return cpu_to_le16(dur); @@ -239,7 +239,7 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, u16 dur; struct ieee80211_supported_band *sband; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + sband = local->hw.wiphy->bands[frame_txctl->band]; short_preamble = false; @@ -253,11 +253,11 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, } /* Data frame duration */ - dur = ieee80211_frame_duration(local, frame_len, rate->bitrate, + dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate, erp, short_preamble); if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) { /* ACK duration */ - dur += ieee80211_frame_duration(local, 10, rate->bitrate, + dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate, erp, short_preamble); } @@ -909,10 +909,8 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local, int i; sband = local->hw.wiphy->bands[band]; - if (!sband) { - WARN_ON(1); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - } + if (WARN_ON(!sband)) + return 1; if (band == IEEE80211_BAND_2GHZ) mandatory_flag = IEEE80211_RATE_MANDATORY_B; @@ -1146,10 +1144,8 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, int i, j; sband = local->hw.wiphy->bands[band]; - if (!sband) { - WARN_ON(1); - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - } + if (WARN_ON(!sband)) + return 1; bitrates = sband->bitrates; num_rates = sband->n_bitrates; @@ -1797,3 +1793,11 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, } return 0; } + +int ieee80211_ave_rssi(struct ieee80211_vif *vif) +{ + struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + return ifmgd->ave_beacon_signal; +} diff --git a/net/mac80211/work.c b/net/mac80211/work.c index c6e230efa049..b2650a9d45ff 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -122,9 +122,6 @@ static void ieee80211_work_work(struct work_struct *work) enum work_action rma; bool remain_off_channel = false; - if (local->scanning) - return; - /* * ieee80211_queue_work() should have picked up most cases, * here we'll pick the rest. @@ -134,6 +131,11 @@ static void ieee80211_work_work(struct work_struct *work) mutex_lock(&local->mtx); + if (local->scanning) { + mutex_unlock(&local->mtx); + return; + } + ieee80211_recalc_idle(local); list_for_each_entry_safe(wk, tmp, &local->work_list, list) { @@ -226,13 +228,8 @@ static void ieee80211_work_work(struct work_struct *work) run_again(local, jiffies + HZ/2); } - if (list_empty(&local->work_list) && local->scan_req && - !local->scanning) - ieee80211_queue_delayed_work(&local->hw, - &local->scan_work, - round_jiffies_relative(0)); - ieee80211_recalc_idle(local); + ieee80211_run_deferred_scan(local); mutex_unlock(&local->mtx); |