diff options
Diffstat (limited to 'net/mac80211')
| -rw-r--r-- | net/mac80211/agg-rx.c | 7 | ||||
| -rw-r--r-- | net/mac80211/cfg.c | 6 | ||||
| -rw-r--r-- | net/mac80211/iface.c | 12 | ||||
| -rw-r--r-- | net/mac80211/mlme.c | 38 | ||||
| -rw-r--r-- | net/mac80211/offchannel.c | 16 | ||||
| -rw-r--r-- | net/mac80211/sta_info.c | 4 | ||||
| -rw-r--r-- | net/mac80211/tx.c | 9 | ||||
| -rw-r--r-- | net/mac80211/util.c | 2 | 
8 files changed, 74 insertions, 20 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 26ddb699d69..c649188314c 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c @@ -145,15 +145,20 @@ static void sta_rx_agg_session_timer_expired(unsigned long data)  	struct tid_ampdu_rx *tid_rx;  	unsigned long timeout; +	rcu_read_lock();  	tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[*ptid]); -	if (!tid_rx) +	if (!tid_rx) { +		rcu_read_unlock();  		return; +	}  	timeout = tid_rx->last_rx + TU_TO_JIFFIES(tid_rx->timeout);  	if (time_is_after_jiffies(timeout)) {  		mod_timer(&tid_rx->session_timer, timeout); +		rcu_read_unlock();  		return;  	} +	rcu_read_unlock();  #ifdef CONFIG_MAC80211_HT_DEBUG  	printk(KERN_DEBUG "rx session timer expired on tid %d\n", (u16)*ptid); diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 495831ee48f..e9cecca5c44 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -533,16 +533,16 @@ static void ieee80211_get_et_stats(struct wiphy *wiphy,  		sinfo.filled = 0;  		sta_set_sinfo(sta, &sinfo); -		if (sinfo.filled | STATION_INFO_TX_BITRATE) +		if (sinfo.filled & STATION_INFO_TX_BITRATE)  			data[i] = 100000 *  				cfg80211_calculate_bitrate(&sinfo.txrate);  		i++; -		if (sinfo.filled | STATION_INFO_RX_BITRATE) +		if (sinfo.filled & STATION_INFO_RX_BITRATE)  			data[i] = 100000 *  				cfg80211_calculate_bitrate(&sinfo.rxrate);  		i++; -		if (sinfo.filled | STATION_INFO_SIGNAL_AVG) +		if (sinfo.filled & STATION_INFO_SIGNAL_AVG)  			data[i] = (u8)sinfo.signal_avg;  		i++;  	} else { diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index d4c19a7773d..8664111d056 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -637,6 +637,18 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,  		ieee80211_configure_filter(local);  		break;  	default: +		mutex_lock(&local->mtx); +		if (local->hw_roc_dev == sdata->dev && +		    local->hw_roc_channel) { +			/* ignore return value since this is racy */ +			drv_cancel_remain_on_channel(local); +			ieee80211_queue_work(&local->hw, &local->hw_roc_done); +		} +		mutex_unlock(&local->mtx); + +		flush_work(&local->hw_roc_start); +		flush_work(&local->hw_roc_done); +  		flush_work(&sdata->work);  		/*  		 * When we get here, the interface is marked down. diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 04c30630898..91d84cc77bb 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1220,6 +1220,22 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,  	sdata->vif.bss_conf.qos = true;  } +static void __ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) +{ +	lockdep_assert_held(&sdata->local->mtx); + +	sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | +				IEEE80211_STA_BEACON_POLL); +	ieee80211_run_deferred_scan(sdata->local); +} + +static void ieee80211_stop_poll(struct ieee80211_sub_if_data *sdata) +{ +	mutex_lock(&sdata->local->mtx); +	__ieee80211_stop_poll(sdata); +	mutex_unlock(&sdata->local->mtx); +} +  static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata,  					   u16 capab, bool erp_valid, u8 erp)  { @@ -1285,8 +1301,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,  	sdata->u.mgd.flags |= IEEE80211_STA_RESET_SIGNAL_AVE;  	/* just to be sure */ -	sdata->u.mgd.flags &= ~(IEEE80211_STA_CONNECTION_POLL | -				IEEE80211_STA_BEACON_POLL); +	ieee80211_stop_poll(sdata);  	ieee80211_led_assoc(local, 1); @@ -1456,8 +1471,7 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)  		return;  	} -	ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | -			  IEEE80211_STA_BEACON_POLL); +	__ieee80211_stop_poll(sdata);  	mutex_lock(&local->iflist_mtx);  	ieee80211_recalc_ps(local, -1); @@ -1477,7 +1491,6 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)  		  round_jiffies_up(jiffies +  				   IEEE80211_CONNECTION_IDLE_TIME));  out: -	ieee80211_run_deferred_scan(local);  	mutex_unlock(&local->mtx);  } @@ -2408,7 +2421,11 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,  		net_dbg_ratelimited("%s: cancelling probereq poll due to a received beacon\n",  				    sdata->name);  #endif +		mutex_lock(&local->mtx);  		ifmgd->flags &= ~IEEE80211_STA_BEACON_POLL; +		ieee80211_run_deferred_scan(local); +		mutex_unlock(&local->mtx); +  		mutex_lock(&local->iflist_mtx);  		ieee80211_recalc_ps(local, -1);  		mutex_unlock(&local->iflist_mtx); @@ -2595,8 +2612,7 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,  	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;  	u8 frame_buf[DEAUTH_DISASSOC_LEN]; -	ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL | -			  IEEE80211_STA_BEACON_POLL); +	ieee80211_stop_poll(sdata);  	ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,  			       false, frame_buf); @@ -2874,8 +2890,7 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)  	u32 flags;  	if (sdata->vif.type == NL80211_IFTYPE_STATION) { -		sdata->u.mgd.flags &= ~(IEEE80211_STA_BEACON_POLL | -					IEEE80211_STA_CONNECTION_POLL); +		__ieee80211_stop_poll(sdata);  		/* let's probe the connection once */  		flags = sdata->local->hw.flags; @@ -2944,7 +2959,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)  	if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))  		add_timer(&ifmgd->chswitch_timer);  	ieee80211_sta_reset_beacon_monitor(sdata); + +	mutex_lock(&sdata->local->mtx);  	ieee80211_restart_sta_timer(sdata); +	mutex_unlock(&sdata->local->mtx);  }  #endif @@ -3106,7 +3124,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,  	}  	local->oper_channel = cbss->channel; -	ieee80211_hw_config(local, 0); +	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);  	if (!have_sta) {  		u32 rates = 0, basic_rates = 0; diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index f054e94901a..935aa4b6dee 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c @@ -234,6 +234,22 @@ static void ieee80211_hw_roc_done(struct work_struct *work)  		return;  	} +	/* was never transmitted */ +	if (local->hw_roc_skb) { +		u64 cookie; + +		cookie = local->hw_roc_cookie ^ 2; + +		cfg80211_mgmt_tx_status(local->hw_roc_dev, cookie, +					local->hw_roc_skb->data, +					local->hw_roc_skb->len, false, +					GFP_KERNEL); + +		kfree_skb(local->hw_roc_skb); +		local->hw_roc_skb = NULL; +		local->hw_roc_skb_for_status = NULL; +	} +  	if (!local->hw_roc_for_tx)  		cfg80211_remain_on_channel_expired(local->hw_roc_dev,  						   local->hw_roc_cookie, diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index f5b1638fbf8..de455f8bbb9 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -378,7 +378,7 @@ static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)  	/* make the station visible */  	sta_info_hash_add(local, sta); -	list_add(&sta->list, &local->sta_list); +	list_add_rcu(&sta->list, &local->sta_list);  	set_sta_flag(sta, WLAN_STA_INSERTED); @@ -688,7 +688,7 @@ int __must_check __sta_info_destroy(struct sta_info *sta)  	if (ret)  		return ret; -	list_del(&sta->list); +	list_del_rcu(&sta->list);  	mutex_lock(&local->key_mtx);  	for (i = 0; i < NUM_DEFAULT_KEYS; i++) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 847215bb2a6..e453212fa17 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -1737,7 +1737,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,  	__le16 fc;  	struct ieee80211_hdr hdr;  	struct ieee80211s_hdr mesh_hdr __maybe_unused; -	struct mesh_path __maybe_unused *mppath = NULL; +	struct mesh_path __maybe_unused *mppath = NULL, *mpath = NULL;  	const u8 *encaps_data;  	int encaps_len, skip_header_bytes;  	int nh_pos, h_pos; @@ -1803,8 +1803,11 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,  			goto fail;  		}  		rcu_read_lock(); -		if (!is_multicast_ether_addr(skb->data)) -			mppath = mpp_path_lookup(skb->data, sdata); +		if (!is_multicast_ether_addr(skb->data)) { +			mpath = mesh_path_lookup(skb->data, sdata); +			if (!mpath) +				mppath = mpp_path_lookup(skb->data, sdata); +		}  		/*  		 * Use address extension if it is a packet from diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a44c6807df0..8dd4712620f 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1271,7 +1271,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)  			enum ieee80211_sta_state state;  			for (state = IEEE80211_STA_NOTEXIST; -			     state < sta->sta_state - 1; state++) +			     state < sta->sta_state; state++)  				WARN_ON(drv_sta_state(local, sta->sdata, sta,  						      state, state + 1));  		}  |