proc: use seq_puts()/seq_putc() where possible
[linux-2.6/next.git] / drivers / net / wireless / iwlwifi / iwl-legacy.c
bloba08b4e56e6b169dad9ab17b6039beb41e2485c8f
1 /******************************************************************************
3 * GPL LICENSE SUMMARY
5 * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
19 * USA
21 * The full GNU General Public License is included in this distribution
22 * in the file called LICENSE.GPL.
24 * Contact Information:
25 * Intel Linux Wireless <ilw@linux.intel.com>
26 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27 *****************************************************************************/
29 #include <linux/kernel.h>
30 #include <net/mac80211.h>
32 #include "iwl-dev.h"
33 #include "iwl-core.h"
34 #include "iwl-helpers.h"
35 #include "iwl-legacy.h"
37 static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
39 if (test_bit(STATUS_EXIT_PENDING, &priv->status))
40 return;
42 if (!ctx->is_active)
43 return;
45 ctx->qos_data.def_qos_parm.qos_flags = 0;
47 if (ctx->qos_data.qos_active)
48 ctx->qos_data.def_qos_parm.qos_flags |=
49 QOS_PARAM_FLG_UPDATE_EDCA_MSK;
51 if (ctx->ht.enabled)
52 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
54 IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
55 ctx->qos_data.qos_active,
56 ctx->qos_data.def_qos_parm.qos_flags);
58 iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
59 sizeof(struct iwl_qosparam_cmd),
60 &ctx->qos_data.def_qos_parm, NULL);
63 /**
64 * iwl_legacy_mac_config - mac80211 config callback
66 int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
68 struct iwl_priv *priv = hw->priv;
69 const struct iwl_channel_info *ch_info;
70 struct ieee80211_conf *conf = &hw->conf;
71 struct ieee80211_channel *channel = conf->channel;
72 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
73 struct iwl_rxon_context *ctx;
74 unsigned long flags = 0;
75 int ret = 0;
76 u16 ch;
77 int scan_active = 0;
78 bool ht_changed[NUM_IWL_RXON_CTX] = {};
80 if (WARN_ON(!priv->cfg->ops->legacy))
81 return -EOPNOTSUPP;
83 mutex_lock(&priv->mutex);
85 IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
86 channel->hw_value, changed);
88 if (unlikely(!priv->cfg->mod_params->disable_hw_scan &&
89 test_bit(STATUS_SCANNING, &priv->status))) {
90 scan_active = 1;
91 IWL_DEBUG_MAC80211(priv, "leave - scanning\n");
94 if (changed & (IEEE80211_CONF_CHANGE_SMPS |
95 IEEE80211_CONF_CHANGE_CHANNEL)) {
96 /* mac80211 uses static for non-HT which is what we want */
97 priv->current_ht_config.smps = conf->smps_mode;
100 * Recalculate chain counts.
102 * If monitor mode is enabled then mac80211 will
103 * set up the SM PS mode to OFF if an HT channel is
104 * configured.
106 if (priv->cfg->ops->hcmd->set_rxon_chain)
107 for_each_context(priv, ctx)
108 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
111 /* during scanning mac80211 will delay channel setting until
112 * scan finish with changed = 0
114 if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
115 if (scan_active)
116 goto set_ch_out;
118 ch = channel->hw_value;
119 ch_info = iwl_get_channel_info(priv, channel->band, ch);
120 if (!is_channel_valid(ch_info)) {
121 IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
122 ret = -EINVAL;
123 goto set_ch_out;
126 spin_lock_irqsave(&priv->lock, flags);
128 for_each_context(priv, ctx) {
129 /* Configure HT40 channels */
130 if (ctx->ht.enabled != conf_is_ht(conf)) {
131 ctx->ht.enabled = conf_is_ht(conf);
132 ht_changed[ctx->ctxid] = true;
134 if (ctx->ht.enabled) {
135 if (conf_is_ht40_minus(conf)) {
136 ctx->ht.extension_chan_offset =
137 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
138 ctx->ht.is_40mhz = true;
139 } else if (conf_is_ht40_plus(conf)) {
140 ctx->ht.extension_chan_offset =
141 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
142 ctx->ht.is_40mhz = true;
143 } else {
144 ctx->ht.extension_chan_offset =
145 IEEE80211_HT_PARAM_CHA_SEC_NONE;
146 ctx->ht.is_40mhz = false;
148 } else
149 ctx->ht.is_40mhz = false;
152 * Default to no protection. Protection mode will
153 * later be set from BSS config in iwl_ht_conf
155 ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
157 /* if we are switching from ht to 2.4 clear flags
158 * from any ht related info since 2.4 does not
159 * support ht */
160 if ((le16_to_cpu(ctx->staging.channel) != ch))
161 ctx->staging.flags = 0;
163 iwl_set_rxon_channel(priv, channel, ctx);
164 iwl_set_rxon_ht(priv, ht_conf);
166 iwl_set_flags_for_band(priv, ctx, channel->band,
167 ctx->vif);
170 spin_unlock_irqrestore(&priv->lock, flags);
172 if (priv->cfg->ops->legacy->update_bcast_stations)
173 ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
175 set_ch_out:
176 /* The list of supported rates and rate mask can be different
177 * for each band; since the band may have changed, reset
178 * the rate mask to what mac80211 lists */
179 iwl_set_rate(priv);
182 if (changed & (IEEE80211_CONF_CHANGE_PS |
183 IEEE80211_CONF_CHANGE_IDLE)) {
184 ret = iwl_power_update_mode(priv, false);
185 if (ret)
186 IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
189 if (changed & IEEE80211_CONF_CHANGE_POWER) {
190 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
191 priv->tx_power_user_lmt, conf->power_level);
193 iwl_set_tx_power(priv, conf->power_level, false);
196 if (!iwl_is_ready(priv)) {
197 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
198 goto out;
201 if (scan_active)
202 goto out;
204 for_each_context(priv, ctx) {
205 if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
206 iwlcore_commit_rxon(priv, ctx);
207 else
208 IWL_DEBUG_INFO(priv,
209 "Not re-sending same RXON configuration.\n");
210 if (ht_changed[ctx->ctxid])
211 iwl_update_qos(priv, ctx);
214 out:
215 IWL_DEBUG_MAC80211(priv, "leave\n");
216 mutex_unlock(&priv->mutex);
217 return ret;
219 EXPORT_SYMBOL(iwl_legacy_mac_config);
221 void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
223 struct iwl_priv *priv = hw->priv;
224 unsigned long flags;
225 /* IBSS can only be the IWL_RXON_CTX_BSS context */
226 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
228 if (WARN_ON(!priv->cfg->ops->legacy))
229 return;
231 mutex_lock(&priv->mutex);
232 IWL_DEBUG_MAC80211(priv, "enter\n");
234 spin_lock_irqsave(&priv->lock, flags);
235 memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
236 spin_unlock_irqrestore(&priv->lock, flags);
238 spin_lock_irqsave(&priv->lock, flags);
240 /* new association get rid of ibss beacon skb */
241 if (priv->beacon_skb)
242 dev_kfree_skb(priv->beacon_skb);
244 priv->beacon_skb = NULL;
246 priv->timestamp = 0;
248 spin_unlock_irqrestore(&priv->lock, flags);
250 iwl_scan_cancel_timeout(priv, 100);
251 if (!iwl_is_ready_rf(priv)) {
252 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
253 mutex_unlock(&priv->mutex);
254 return;
257 /* we are restarting association process
258 * clear RXON_FILTER_ASSOC_MSK bit
260 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
261 iwlcore_commit_rxon(priv, ctx);
263 iwl_set_rate(priv);
265 mutex_unlock(&priv->mutex);
267 IWL_DEBUG_MAC80211(priv, "leave\n");
269 EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
271 static void iwl_ht_conf(struct iwl_priv *priv,
272 struct ieee80211_vif *vif)
274 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
275 struct ieee80211_sta *sta;
276 struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
277 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
279 IWL_DEBUG_ASSOC(priv, "enter:\n");
281 if (!ctx->ht.enabled)
282 return;
284 ctx->ht.protection =
285 bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
286 ctx->ht.non_gf_sta_present =
287 !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
289 ht_conf->single_chain_sufficient = false;
291 switch (vif->type) {
292 case NL80211_IFTYPE_STATION:
293 rcu_read_lock();
294 sta = ieee80211_find_sta(vif, bss_conf->bssid);
295 if (sta) {
296 struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
297 int maxstreams;
299 maxstreams = (ht_cap->mcs.tx_params &
300 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
301 >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
302 maxstreams += 1;
304 if ((ht_cap->mcs.rx_mask[1] == 0) &&
305 (ht_cap->mcs.rx_mask[2] == 0))
306 ht_conf->single_chain_sufficient = true;
307 if (maxstreams <= 1)
308 ht_conf->single_chain_sufficient = true;
309 } else {
311 * If at all, this can only happen through a race
312 * when the AP disconnects us while we're still
313 * setting up the connection, in that case mac80211
314 * will soon tell us about that.
316 ht_conf->single_chain_sufficient = true;
318 rcu_read_unlock();
319 break;
320 case NL80211_IFTYPE_ADHOC:
321 ht_conf->single_chain_sufficient = true;
322 break;
323 default:
324 break;
327 IWL_DEBUG_ASSOC(priv, "leave\n");
330 static inline void iwl_set_no_assoc(struct iwl_priv *priv,
331 struct ieee80211_vif *vif)
333 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
335 iwl_led_disassociate(priv);
337 * inform the ucode that there is no longer an
338 * association and that no more packets should be
339 * sent
341 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
342 ctx->staging.assoc_id = 0;
343 iwlcore_commit_rxon(priv, ctx);
346 static void iwlcore_beacon_update(struct ieee80211_hw *hw,
347 struct ieee80211_vif *vif)
349 struct iwl_priv *priv = hw->priv;
350 unsigned long flags;
351 __le64 timestamp;
352 struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
354 if (!skb)
355 return;
357 IWL_DEBUG_MAC80211(priv, "enter\n");
359 lockdep_assert_held(&priv->mutex);
361 if (!priv->beacon_ctx) {
362 IWL_ERR(priv, "update beacon but no beacon context!\n");
363 dev_kfree_skb(skb);
364 return;
367 spin_lock_irqsave(&priv->lock, flags);
369 if (priv->beacon_skb)
370 dev_kfree_skb(priv->beacon_skb);
372 priv->beacon_skb = skb;
374 timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
375 priv->timestamp = le64_to_cpu(timestamp);
377 IWL_DEBUG_MAC80211(priv, "leave\n");
378 spin_unlock_irqrestore(&priv->lock, flags);
380 if (!iwl_is_ready_rf(priv)) {
381 IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
382 return;
385 priv->cfg->ops->legacy->post_associate(priv);
388 void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
389 struct ieee80211_vif *vif,
390 struct ieee80211_bss_conf *bss_conf,
391 u32 changes)
393 struct iwl_priv *priv = hw->priv;
394 struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
395 int ret;
397 if (WARN_ON(!priv->cfg->ops->legacy))
398 return;
400 IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
402 if (!iwl_is_alive(priv))
403 return;
405 mutex_lock(&priv->mutex);
407 if (changes & BSS_CHANGED_QOS) {
408 unsigned long flags;
410 spin_lock_irqsave(&priv->lock, flags);
411 ctx->qos_data.qos_active = bss_conf->qos;
412 iwl_update_qos(priv, ctx);
413 spin_unlock_irqrestore(&priv->lock, flags);
416 if (changes & BSS_CHANGED_BEACON_ENABLED) {
418 * the add_interface code must make sure we only ever
419 * have a single interface that could be beaconing at
420 * any time.
422 if (vif->bss_conf.enable_beacon)
423 priv->beacon_ctx = ctx;
424 else
425 priv->beacon_ctx = NULL;
428 if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
429 dev_kfree_skb(priv->beacon_skb);
430 priv->beacon_skb = ieee80211_beacon_get(hw, vif);
433 if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
434 iwl_send_rxon_timing(priv, ctx);
436 if (changes & BSS_CHANGED_BSSID) {
437 IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
440 * If there is currently a HW scan going on in the
441 * background then we need to cancel it else the RXON
442 * below/in post_associate will fail.
444 if (iwl_scan_cancel_timeout(priv, 100)) {
445 IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
446 IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
447 mutex_unlock(&priv->mutex);
448 return;
451 /* mac80211 only sets assoc when in STATION mode */
452 if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
453 memcpy(ctx->staging.bssid_addr,
454 bss_conf->bssid, ETH_ALEN);
456 /* currently needed in a few places */
457 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
458 } else {
459 ctx->staging.filter_flags &=
460 ~RXON_FILTER_ASSOC_MSK;
466 * This needs to be after setting the BSSID in case
467 * mac80211 decides to do both changes at once because
468 * it will invoke post_associate.
470 if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
471 iwlcore_beacon_update(hw, vif);
473 if (changes & BSS_CHANGED_ERP_PREAMBLE) {
474 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
475 bss_conf->use_short_preamble);
476 if (bss_conf->use_short_preamble)
477 ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
478 else
479 ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
482 if (changes & BSS_CHANGED_ERP_CTS_PROT) {
483 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
484 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
485 ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
486 else
487 ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
488 if (bss_conf->use_cts_prot)
489 ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
490 else
491 ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
494 if (changes & BSS_CHANGED_BASIC_RATES) {
495 /* XXX use this information
497 * To do that, remove code from iwl_set_rate() and put something
498 * like this here:
500 if (A-band)
501 ctx->staging.ofdm_basic_rates =
502 bss_conf->basic_rates;
503 else
504 ctx->staging.ofdm_basic_rates =
505 bss_conf->basic_rates >> 4;
506 ctx->staging.cck_basic_rates =
507 bss_conf->basic_rates & 0xF;
511 if (changes & BSS_CHANGED_HT) {
512 iwl_ht_conf(priv, vif);
514 if (priv->cfg->ops->hcmd->set_rxon_chain)
515 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
518 if (changes & BSS_CHANGED_ASSOC) {
519 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
520 if (bss_conf->assoc) {
521 priv->timestamp = bss_conf->timestamp;
523 iwl_led_associate(priv);
525 if (!iwl_is_rfkill(priv))
526 priv->cfg->ops->legacy->post_associate(priv);
527 } else
528 iwl_set_no_assoc(priv, vif);
531 if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
532 IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
533 changes);
534 ret = iwl_send_rxon_assoc(priv, ctx);
535 if (!ret) {
536 /* Sync active_rxon with latest change. */
537 memcpy((void *)&ctx->active,
538 &ctx->staging,
539 sizeof(struct iwl_rxon_cmd));
543 if (changes & BSS_CHANGED_BEACON_ENABLED) {
544 if (vif->bss_conf.enable_beacon) {
545 memcpy(ctx->staging.bssid_addr,
546 bss_conf->bssid, ETH_ALEN);
547 memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
548 iwl_led_associate(priv);
549 priv->cfg->ops->legacy->config_ap(priv);
550 } else
551 iwl_set_no_assoc(priv, vif);
554 if (changes & BSS_CHANGED_IBSS) {
555 ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
556 bss_conf->ibss_joined);
557 if (ret)
558 IWL_ERR(priv, "failed to %s IBSS station %pM\n",
559 bss_conf->ibss_joined ? "add" : "remove",
560 bss_conf->bssid);
563 mutex_unlock(&priv->mutex);
565 IWL_DEBUG_MAC80211(priv, "leave\n");
567 EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
569 irqreturn_t iwl_isr_legacy(int irq, void *data)
571 struct iwl_priv *priv = data;
572 u32 inta, inta_mask;
573 u32 inta_fh;
574 unsigned long flags;
575 if (!priv)
576 return IRQ_NONE;
578 spin_lock_irqsave(&priv->lock, flags);
580 /* Disable (but don't clear!) interrupts here to avoid
581 * back-to-back ISRs and sporadic interrupts from our NIC.
582 * If we have something to service, the tasklet will re-enable ints.
583 * If we *don't* have something, we'll re-enable before leaving here. */
584 inta_mask = iwl_read32(priv, CSR_INT_MASK); /* just for debug */
585 iwl_write32(priv, CSR_INT_MASK, 0x00000000);
587 /* Discover which interrupts are active/pending */
588 inta = iwl_read32(priv, CSR_INT);
589 inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
591 /* Ignore interrupt if there's nothing in NIC to service.
592 * This may be due to IRQ shared with another device,
593 * or due to sporadic interrupts thrown from our NIC. */
594 if (!inta && !inta_fh) {
595 IWL_DEBUG_ISR(priv,
596 "Ignore interrupt, inta == 0, inta_fh == 0\n");
597 goto none;
600 if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
601 /* Hardware disappeared. It might have already raised
602 * an interrupt */
603 IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
604 goto unplugged;
607 IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
608 inta, inta_mask, inta_fh);
610 inta &= ~CSR_INT_BIT_SCD;
612 /* iwl_irq_tasklet() will service interrupts and re-enable them */
613 if (likely(inta || inta_fh))
614 tasklet_schedule(&priv->irq_tasklet);
616 unplugged:
617 spin_unlock_irqrestore(&priv->lock, flags);
618 return IRQ_HANDLED;
620 none:
621 /* re-enable interrupts here since we don't have anything to service. */
622 /* only Re-enable if diabled by irq */
623 if (test_bit(STATUS_INT_ENABLED, &priv->status))
624 iwl_enable_interrupts(priv);
625 spin_unlock_irqrestore(&priv->lock, flags);
626 return IRQ_NONE;
628 EXPORT_SYMBOL(iwl_isr_legacy);
631 * iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
632 * function.
634 void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
635 struct ieee80211_tx_info *info,
636 __le16 fc, __le32 *tx_flags)
638 if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
639 *tx_flags |= TX_CMD_FLG_RTS_MSK;
640 *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
641 *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
643 if (!ieee80211_is_mgmt(fc))
644 return;
646 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
647 case cpu_to_le16(IEEE80211_STYPE_AUTH):
648 case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
649 case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
650 case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
651 *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
652 *tx_flags |= TX_CMD_FLG_CTS_MSK;
653 break;
655 } else if (info->control.rates[0].flags &
656 IEEE80211_TX_RC_USE_CTS_PROTECT) {
657 *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
658 *tx_flags |= TX_CMD_FLG_CTS_MSK;
659 *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
662 EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);