PageRenderTime 49ms CodeModel.GetById 19ms app.highlight 24ms RepoModel.GetById 0ms app.codeStats 0ms

/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 782 lines | 511 code | 118 blank | 153 comment | 118 complexity | 20b8401ee2e145944ee0e33c8943f7bf MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/******************************************************************************
  2 *
  3 * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
  4 *
  5 * This program is free software; you can redistribute it and/or modify it
  6 * under the terms of version 2 of the GNU General Public License as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it will be useful, but WITHOUT
 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 12 * more details.
 13 *
 14 * You should have received a copy of the GNU General Public License along with
 15 * this program; if not, write to the Free Software Foundation, Inc.,
 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 17 *
 18 * The full GNU General Public License is included in this distribution in the
 19 * file called LICENSE.
 20 *
 21 * Contact Information:
 22 * Intel Linux Wireless <ilw@linux.intel.com>
 23 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 24 *
 25 *****************************************************************************/
 26
 27#include "iwl-dev.h"
 28#include "iwl-agn.h"
 29#include "iwl-sta.h"
 30#include "iwl-core.h"
 31#include "iwl-agn-calib.h"
 32#include "iwl-helpers.h"
 33
 34static int iwlagn_disable_bss(struct iwl_priv *priv,
 35			      struct iwl_rxon_context *ctx,
 36			      struct iwl_rxon_cmd *send)
 37{
 38	__le32 old_filter = send->filter_flags;
 39	int ret;
 40
 41	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 42	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
 43
 44	send->filter_flags = old_filter;
 45
 46	if (ret)
 47		IWL_ERR(priv, "Error clearing ASSOC_MSK on BSS (%d)\n", ret);
 48
 49	return ret;
 50}
 51
 52static int iwlagn_disable_pan(struct iwl_priv *priv,
 53			      struct iwl_rxon_context *ctx,
 54			      struct iwl_rxon_cmd *send)
 55{
 56	struct iwl_notification_wait disable_wait;
 57	__le32 old_filter = send->filter_flags;
 58	u8 old_dev_type = send->dev_type;
 59	int ret;
 60
 61	iwlagn_init_notification_wait(priv, &disable_wait,
 62				      REPLY_WIPAN_DEACTIVATION_COMPLETE,
 63				      NULL, NULL);
 64
 65	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 66	send->dev_type = RXON_DEV_TYPE_P2P;
 67	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
 68
 69	send->filter_flags = old_filter;
 70	send->dev_type = old_dev_type;
 71
 72	if (ret) {
 73		IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
 74		iwlagn_remove_notification(priv, &disable_wait);
 75	} else {
 76		ret = iwlagn_wait_notification(priv, &disable_wait, HZ);
 77		if (ret)
 78			IWL_ERR(priv, "Timed out waiting for PAN disable\n");
 79	}
 80
 81	return ret;
 82}
 83
 84static void iwlagn_update_qos(struct iwl_priv *priv,
 85			      struct iwl_rxon_context *ctx)
 86{
 87	int ret;
 88
 89	if (!ctx->is_active)
 90		return;
 91
 92	ctx->qos_data.def_qos_parm.qos_flags = 0;
 93
 94	if (ctx->qos_data.qos_active)
 95		ctx->qos_data.def_qos_parm.qos_flags |=
 96			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
 97
 98	if (ctx->ht.enabled)
 99		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
100
101	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
102		      ctx->qos_data.qos_active,
103		      ctx->qos_data.def_qos_parm.qos_flags);
104
105	ret = iwl_send_cmd_pdu(priv, ctx->qos_cmd,
106			       sizeof(struct iwl_qosparam_cmd),
107			       &ctx->qos_data.def_qos_parm);
108	if (ret)
109		IWL_ERR(priv, "Failed to update QoS\n");
110}
111
112static int iwlagn_update_beacon(struct iwl_priv *priv,
113				struct ieee80211_vif *vif)
114{
115	lockdep_assert_held(&priv->mutex);
116
117	dev_kfree_skb(priv->beacon_skb);
118	priv->beacon_skb = ieee80211_beacon_get(priv->hw, vif);
119	if (!priv->beacon_skb)
120		return -ENOMEM;
121	return iwlagn_send_beacon_cmd(priv);
122}
123
124static int iwlagn_send_rxon_assoc(struct iwl_priv *priv,
125			   struct iwl_rxon_context *ctx)
126{
127	int ret = 0;
128	struct iwl_rxon_assoc_cmd rxon_assoc;
129	const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
130	const struct iwl_rxon_cmd *rxon2 = &ctx->active;
131
132	if ((rxon1->flags == rxon2->flags) &&
133	    (rxon1->filter_flags == rxon2->filter_flags) &&
134	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
135	    (rxon1->ofdm_ht_single_stream_basic_rates ==
136	     rxon2->ofdm_ht_single_stream_basic_rates) &&
137	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
138	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
139	    (rxon1->ofdm_ht_triple_stream_basic_rates ==
140	     rxon2->ofdm_ht_triple_stream_basic_rates) &&
141	    (rxon1->acquisition_data == rxon2->acquisition_data) &&
142	    (rxon1->rx_chain == rxon2->rx_chain) &&
143	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
144		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
145		return 0;
146	}
147
148	rxon_assoc.flags = ctx->staging.flags;
149	rxon_assoc.filter_flags = ctx->staging.filter_flags;
150	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
151	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
152	rxon_assoc.reserved1 = 0;
153	rxon_assoc.reserved2 = 0;
154	rxon_assoc.reserved3 = 0;
155	rxon_assoc.ofdm_ht_single_stream_basic_rates =
156	    ctx->staging.ofdm_ht_single_stream_basic_rates;
157	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
158	    ctx->staging.ofdm_ht_dual_stream_basic_rates;
159	rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
160	rxon_assoc.ofdm_ht_triple_stream_basic_rates =
161		 ctx->staging.ofdm_ht_triple_stream_basic_rates;
162	rxon_assoc.acquisition_data = ctx->staging.acquisition_data;
163
164	ret = iwl_send_cmd_pdu_async(priv, ctx->rxon_assoc_cmd,
165				     sizeof(rxon_assoc), &rxon_assoc, NULL);
166	if (ret)
167		return ret;
168
169	return ret;
170}
171
172static int iwlagn_rxon_disconn(struct iwl_priv *priv,
173			       struct iwl_rxon_context *ctx)
174{
175	int ret;
176	struct iwl_rxon_cmd *active = (void *)&ctx->active;
177
178	if (ctx->ctxid == IWL_RXON_CTX_BSS)
179		ret = iwlagn_disable_bss(priv, ctx, &ctx->staging);
180	else
181		ret = iwlagn_disable_pan(priv, ctx, &ctx->staging);
182	if (ret)
183		return ret;
184
185	/*
186	 * Un-assoc RXON clears the station table and WEP
187	 * keys, so we have to restore those afterwards.
188	 */
189	iwl_clear_ucode_stations(priv, ctx);
190	iwl_restore_stations(priv, ctx);
191	ret = iwl_restore_default_wep_keys(priv, ctx);
192	if (ret) {
193		IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
194		return ret;
195	}
196
197	memcpy(active, &ctx->staging, sizeof(*active));
198	return 0;
199}
200
201static int iwlagn_rxon_connect(struct iwl_priv *priv,
202			       struct iwl_rxon_context *ctx)
203{
204	int ret;
205	struct iwl_rxon_cmd *active = (void *)&ctx->active;
206
207	/* RXON timing must be before associated RXON */
208	ret = iwl_send_rxon_timing(priv, ctx);
209	if (ret) {
210		IWL_ERR(priv, "Failed to send timing (%d)!\n", ret);
211		return ret;
212	}
213	/* QoS info may be cleared by previous un-assoc RXON */
214	iwlagn_update_qos(priv, ctx);
215
216	/*
217	 * We'll run into this code path when beaconing is
218	 * enabled, but then we also need to send the beacon
219	 * to the device.
220	 */
221	if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_AP)) {
222		ret = iwlagn_update_beacon(priv, ctx->vif);
223		if (ret) {
224			IWL_ERR(priv,
225				"Error sending required beacon (%d)!\n",
226				ret);
227			return ret;
228		}
229	}
230
231	priv->start_calib = 0;
232	/*
233	 * Apply the new configuration.
234	 *
235	 * Associated RXON doesn't clear the station table in uCode,
236	 * so we don't need to restore stations etc. after this.
237	 */
238	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
239		      sizeof(struct iwl_rxon_cmd), &ctx->staging);
240	if (ret) {
241		IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
242		return ret;
243	}
244	memcpy(active, &ctx->staging, sizeof(*active));
245
246	iwl_reprogram_ap_sta(priv, ctx);
247
248	/* IBSS beacon needs to be sent after setting assoc */
249	if (ctx->vif && (ctx->vif->type == NL80211_IFTYPE_ADHOC))
250		if (iwlagn_update_beacon(priv, ctx->vif))
251			IWL_ERR(priv, "Error sending IBSS beacon\n");
252	iwl_init_sensitivity(priv);
253
254	/*
255	 * If we issue a new RXON command which required a tune then
256	 * we must send a new TXPOWER command or we won't be able to
257	 * Tx any frames.
258	 *
259	 * It's expected we set power here if channel is changing.
260	 */
261	ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
262	if (ret) {
263		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
264		return ret;
265	}
266	return 0;
267}
268
269/**
270 * iwlagn_commit_rxon - commit staging_rxon to hardware
271 *
272 * The RXON command in staging_rxon is committed to the hardware and
273 * the active_rxon structure is updated with the new data.  This
274 * function correctly transitions out of the RXON_ASSOC_MSK state if
275 * a HW tune is required based on the RXON structure changes.
276 *
277 * The connect/disconnect flow should be as the following:
278 *
279 * 1. make sure send RXON command with association bit unset if not connect
280 *	this should include the channel and the band for the candidate
281 *	to be connected to
282 * 2. Add Station before RXON association with the AP
283 * 3. RXON_timing has to send before RXON for connection
284 * 4. full RXON command - associated bit set
285 * 5. use RXON_ASSOC command to update any flags changes
286 */
287int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
288{
289	/* cast away the const for active_rxon in this function */
290	struct iwl_rxon_cmd *active = (void *)&ctx->active;
291	bool new_assoc = !!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
292	int ret;
293
294	lockdep_assert_held(&priv->mutex);
295
296	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
297		return -EINVAL;
298
299	if (!iwl_is_alive(priv))
300		return -EBUSY;
301
302	/* This function hardcodes a bunch of dual-mode assumptions */
303	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
304
305	if (!ctx->is_active)
306		return 0;
307
308	/* always get timestamp with Rx frame */
309	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
310
311	if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) {
312		struct ieee80211_channel *chan = priv->_agn.hw_roc_channel;
313
314		iwl_set_rxon_channel(priv, chan, ctx);
315		iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
316		ctx->staging.filter_flags |=
317			RXON_FILTER_ASSOC_MSK |
318			RXON_FILTER_PROMISC_MSK |
319			RXON_FILTER_CTL2HOST_MSK;
320		ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
321		new_assoc = true;
322
323		if (memcmp(&ctx->staging, &ctx->active,
324			   sizeof(ctx->staging)) == 0)
325			return 0;
326	}
327
328	/*
329	 * force CTS-to-self frames protection if RTS-CTS is not preferred
330	 * one aggregation protection method
331	 */
332	if (!(priv->cfg->ht_params &&
333	      priv->cfg->ht_params->use_rts_for_aggregation))
334		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
335
336	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
337	    !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
338		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
339	else
340		ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
341
342	iwl_print_rx_config_cmd(priv, ctx);
343	ret = iwl_check_rxon_cmd(priv, ctx);
344	if (ret) {
345		IWL_ERR(priv, "Invalid RXON configuration. Not committing.\n");
346		return -EINVAL;
347	}
348
349	/*
350	 * receive commit_rxon request
351	 * abort any previous channel switch if still in process
352	 */
353	if (test_bit(STATUS_CHANNEL_SWITCH_PENDING, &priv->status) &&
354	    (priv->switch_channel != ctx->staging.channel)) {
355		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
356			      le16_to_cpu(priv->switch_channel));
357		iwl_chswitch_done(priv, false);
358	}
359
360	/*
361	 * If we don't need to send a full RXON, we can use
362	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
363	 * and other flags for the current radio configuration.
364	 */
365	if (!iwl_full_rxon_required(priv, ctx)) {
366		ret = iwlagn_send_rxon_assoc(priv, ctx);
367		if (ret) {
368			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
369			return ret;
370		}
371
372		memcpy(active, &ctx->staging, sizeof(*active));
373		/*
374		 * We do not commit tx power settings while channel changing,
375		 * do it now if after settings changed.
376		 */
377		iwl_set_tx_power(priv, priv->tx_power_next, false);
378		return 0;
379	}
380
381	if (priv->cfg->ops->hcmd->set_pan_params) {
382		ret = priv->cfg->ops->hcmd->set_pan_params(priv);
383		if (ret)
384			return ret;
385	}
386
387	iwl_set_rxon_hwcrypto(priv, ctx, !iwlagn_mod_params.sw_crypto);
388
389	IWL_DEBUG_INFO(priv,
390		       "Going to commit RXON\n"
391		       "  * with%s RXON_FILTER_ASSOC_MSK\n"
392		       "  * channel = %d\n"
393		       "  * bssid = %pM\n",
394		       (new_assoc ? "" : "out"),
395		       le16_to_cpu(ctx->staging.channel),
396		       ctx->staging.bssid_addr);
397
398	/*
399	 * Always clear associated first, but with the correct config.
400	 * This is required as for example station addition for the
401	 * AP station must be done after the BSSID is set to correctly
402	 * set up filters in the device.
403	 */
404	ret = iwlagn_rxon_disconn(priv, ctx);
405	if (ret)
406		return ret;
407
408	if (new_assoc)
409		return iwlagn_rxon_connect(priv, ctx);
410
411	return 0;
412}
413
414int iwlagn_mac_config(struct ieee80211_hw *hw, u32 changed)
415{
416	struct iwl_priv *priv = hw->priv;
417	struct iwl_rxon_context *ctx;
418	struct ieee80211_conf *conf = &hw->conf;
419	struct ieee80211_channel *channel = conf->channel;
420	const struct iwl_channel_info *ch_info;
421	int ret = 0;
422
423	IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
424
425	mutex_lock(&priv->mutex);
426
427	if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
428		IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
429		goto out;
430	}
431
432	if (!iwl_is_ready(priv)) {
433		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
434		goto out;
435	}
436
437	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
438		       IEEE80211_CONF_CHANGE_CHANNEL)) {
439		/* mac80211 uses static for non-HT which is what we want */
440		priv->current_ht_config.smps = conf->smps_mode;
441
442		/*
443		 * Recalculate chain counts.
444		 *
445		 * If monitor mode is enabled then mac80211 will
446		 * set up the SM PS mode to OFF if an HT channel is
447		 * configured.
448		 */
449		if (priv->cfg->ops->hcmd->set_rxon_chain)
450			for_each_context(priv, ctx)
451				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
452	}
453
454	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
455		unsigned long flags;
456
457		ch_info = iwl_get_channel_info(priv, channel->band,
458					       channel->hw_value);
459		if (!is_channel_valid(ch_info)) {
460			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
461			ret = -EINVAL;
462			goto out;
463		}
464
465		spin_lock_irqsave(&priv->lock, flags);
466
467		for_each_context(priv, ctx) {
468			/* Configure HT40 channels */
469			if (ctx->ht.enabled != conf_is_ht(conf))
470				ctx->ht.enabled = conf_is_ht(conf);
471
472			if (ctx->ht.enabled) {
473				if (conf_is_ht40_minus(conf)) {
474					ctx->ht.extension_chan_offset =
475						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
476					ctx->ht.is_40mhz = true;
477				} else if (conf_is_ht40_plus(conf)) {
478					ctx->ht.extension_chan_offset =
479						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
480					ctx->ht.is_40mhz = true;
481				} else {
482					ctx->ht.extension_chan_offset =
483						IEEE80211_HT_PARAM_CHA_SEC_NONE;
484					ctx->ht.is_40mhz = false;
485				}
486			} else
487				ctx->ht.is_40mhz = false;
488
489			/*
490			 * Default to no protection. Protection mode will
491			 * later be set from BSS config in iwl_ht_conf
492			 */
493			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
494
495			/* if we are switching from ht to 2.4 clear flags
496			 * from any ht related info since 2.4 does not
497			 * support ht */
498			if (le16_to_cpu(ctx->staging.channel) !=
499			    channel->hw_value)
500				ctx->staging.flags = 0;
501
502			iwl_set_rxon_channel(priv, channel, ctx);
503			iwl_set_rxon_ht(priv, &priv->current_ht_config);
504
505			iwl_set_flags_for_band(priv, ctx, channel->band,
506					       ctx->vif);
507		}
508
509		spin_unlock_irqrestore(&priv->lock, flags);
510
511		iwl_update_bcast_stations(priv);
512
513		/*
514		 * The list of supported rates and rate mask can be different
515		 * for each band; since the band may have changed, reset
516		 * the rate mask to what mac80211 lists.
517		 */
518		iwl_set_rate(priv);
519	}
520
521	if (changed & (IEEE80211_CONF_CHANGE_PS |
522			IEEE80211_CONF_CHANGE_IDLE)) {
523		ret = iwl_power_update_mode(priv, false);
524		if (ret)
525			IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
526	}
527
528	if (changed & IEEE80211_CONF_CHANGE_POWER) {
529		IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
530			priv->tx_power_user_lmt, conf->power_level);
531
532		iwl_set_tx_power(priv, conf->power_level, false);
533	}
534
535	for_each_context(priv, ctx) {
536		if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
537			continue;
538		iwlagn_commit_rxon(priv, ctx);
539	}
540 out:
541	mutex_unlock(&priv->mutex);
542	return ret;
543}
544
545static void iwlagn_check_needed_chains(struct iwl_priv *priv,
546				       struct iwl_rxon_context *ctx,
547				       struct ieee80211_bss_conf *bss_conf)
548{
549	struct ieee80211_vif *vif = ctx->vif;
550	struct iwl_rxon_context *tmp;
551	struct ieee80211_sta *sta;
552	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
553	struct ieee80211_sta_ht_cap *ht_cap;
554	bool need_multiple;
555
556	lockdep_assert_held(&priv->mutex);
557
558	switch (vif->type) {
559	case NL80211_IFTYPE_STATION:
560		rcu_read_lock();
561		sta = ieee80211_find_sta(vif, bss_conf->bssid);
562		if (!sta) {
563			/*
564			 * If at all, this can only happen through a race
565			 * when the AP disconnects us while we're still
566			 * setting up the connection, in that case mac80211
567			 * will soon tell us about that.
568			 */
569			need_multiple = false;
570			rcu_read_unlock();
571			break;
572		}
573
574		ht_cap = &sta->ht_cap;
575
576		need_multiple = true;
577
578		/*
579		 * If the peer advertises no support for receiving 2 and 3
580		 * stream MCS rates, it can't be transmitting them either.
581		 */
582		if (ht_cap->mcs.rx_mask[1] == 0 &&
583		    ht_cap->mcs.rx_mask[2] == 0) {
584			need_multiple = false;
585		} else if (!(ht_cap->mcs.tx_params &
586						IEEE80211_HT_MCS_TX_DEFINED)) {
587			/* If it can't TX MCS at all ... */
588			need_multiple = false;
589		} else if (ht_cap->mcs.tx_params &
590						IEEE80211_HT_MCS_TX_RX_DIFF) {
591			int maxstreams;
592
593			/*
594			 * But if it can receive them, it might still not
595			 * be able to transmit them, which is what we need
596			 * to check here -- so check the number of streams
597			 * it advertises for TX (if different from RX).
598			 */
599
600			maxstreams = (ht_cap->mcs.tx_params &
601				 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK);
602			maxstreams >>=
603				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
604			maxstreams += 1;
605
606			if (maxstreams <= 1)
607				need_multiple = false;
608		}
609
610		rcu_read_unlock();
611		break;
612	case NL80211_IFTYPE_ADHOC:
613		/* currently */
614		need_multiple = false;
615		break;
616	default:
617		/* only AP really */
618		need_multiple = true;
619		break;
620	}
621
622	ctx->ht_need_multiple_chains = need_multiple;
623
624	if (!need_multiple) {
625		/* check all contexts */
626		for_each_context(priv, tmp) {
627			if (!tmp->vif)
628				continue;
629			if (tmp->ht_need_multiple_chains) {
630				need_multiple = true;
631				break;
632			}
633		}
634	}
635
636	ht_conf->single_chain_sufficient = !need_multiple;
637}
638
639void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
640			     struct ieee80211_vif *vif,
641			     struct ieee80211_bss_conf *bss_conf,
642			     u32 changes)
643{
644	struct iwl_priv *priv = hw->priv;
645	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
646	int ret;
647	bool force = false;
648
649	mutex_lock(&priv->mutex);
650
651	if (unlikely(!iwl_is_ready(priv))) {
652		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
653		mutex_unlock(&priv->mutex);
654		return;
655        }
656
657	if (unlikely(!ctx->vif)) {
658		IWL_DEBUG_MAC80211(priv, "leave - vif is NULL\n");
659		mutex_unlock(&priv->mutex);
660		return;
661	}
662
663	if (changes & BSS_CHANGED_BEACON_INT)
664		force = true;
665
666	if (changes & BSS_CHANGED_QOS) {
667		ctx->qos_data.qos_active = bss_conf->qos;
668		iwlagn_update_qos(priv, ctx);
669	}
670
671	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
672	if (vif->bss_conf.use_short_preamble)
673		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
674	else
675		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
676
677	if (changes & BSS_CHANGED_ASSOC) {
678		if (bss_conf->assoc) {
679			priv->timestamp = bss_conf->timestamp;
680			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
681		} else {
682			/*
683			 * If we disassociate while there are pending
684			 * frames, just wake up the queues and let the
685			 * frames "escape" ... This shouldn't really
686			 * be happening to start with, but we should
687			 * not get stuck in this case either since it
688			 * can happen if userspace gets confused.
689			 */
690			if (ctx->last_tx_rejected) {
691				ctx->last_tx_rejected = false;
692				iwl_wake_any_queue(priv, ctx);
693			}
694			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
695		}
696	}
697
698	if (ctx->ht.enabled) {
699		ctx->ht.protection = bss_conf->ht_operation_mode &
700					IEEE80211_HT_OP_MODE_PROTECTION;
701		ctx->ht.non_gf_sta_present = !!(bss_conf->ht_operation_mode &
702					IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
703		iwlagn_check_needed_chains(priv, ctx, bss_conf);
704		iwl_set_rxon_ht(priv, &priv->current_ht_config);
705	}
706
707	if (priv->cfg->ops->hcmd->set_rxon_chain)
708		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
709
710	if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
711		ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
712	else
713		ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
714
715	if (bss_conf->use_cts_prot)
716		ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
717	else
718		ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
719
720	memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
721
722	if (vif->type == NL80211_IFTYPE_AP ||
723	    vif->type == NL80211_IFTYPE_ADHOC) {
724		if (vif->bss_conf.enable_beacon) {
725			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
726			priv->beacon_ctx = ctx;
727		} else {
728			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
729			priv->beacon_ctx = NULL;
730		}
731	}
732
733	if (force || memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
734		iwlagn_commit_rxon(priv, ctx);
735
736	if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc) {
737		/*
738		 * The chain noise calibration will enable PM upon
739		 * completion. If calibration has already been run
740		 * then we need to enable power management here.
741		 */
742		if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
743			iwl_power_update_mode(priv, false);
744
745		/* Enable RX differential gain and sensitivity calibrations */
746		iwl_chain_noise_reset(priv);
747		priv->start_calib = 1;
748	}
749
750	if (changes & BSS_CHANGED_IBSS) {
751		ret = iwlagn_manage_ibss_station(priv, vif,
752						 bss_conf->ibss_joined);
753		if (ret)
754			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
755				bss_conf->ibss_joined ? "add" : "remove",
756				bss_conf->bssid);
757	}
758
759	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_ADHOC &&
760	    priv->beacon_ctx) {
761		if (iwlagn_update_beacon(priv, vif))
762			IWL_ERR(priv, "Error sending IBSS beacon\n");
763	}
764
765	mutex_unlock(&priv->mutex);
766}
767
768void iwlagn_post_scan(struct iwl_priv *priv)
769{
770	struct iwl_rxon_context *ctx;
771
772	/*
773	 * Since setting the RXON may have been deferred while
774	 * performing the scan, fire one off if needed
775	 */
776	for_each_context(priv, ctx)
777		if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
778			iwlagn_commit_rxon(priv, ctx);
779
780	if (priv->cfg->ops->hcmd->set_pan_params)
781		priv->cfg->ops->hcmd->set_pan_params(priv);
782}