ipv6: Use ERR_CAST in addrconf_dst_alloc.
[pandora-kernel.git] / drivers / net / wireless / iwlwifi / iwl-legacy.c
1 /******************************************************************************
2  *
3  * GPL LICENSE SUMMARY
4  *
5  * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
6  *
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.
10  *
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.
15  *
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
20  *
21  * The full GNU General Public License is included in this distribution
22  * in the file called LICENSE.GPL.
23  *
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  *****************************************************************************/
28
29 #include <linux/kernel.h>
30 #include <net/mac80211.h>
31
32 #include "iwl-dev.h"
33 #include "iwl-core.h"
34 #include "iwl-helpers.h"
35 #include "iwl-legacy.h"
36
37 static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
38 {
39         if (test_bit(STATUS_EXIT_PENDING, &priv->status))
40                 return;
41
42         if (!ctx->is_active)
43                 return;
44
45         ctx->qos_data.def_qos_parm.qos_flags = 0;
46
47         if (ctx->qos_data.qos_active)
48                 ctx->qos_data.def_qos_parm.qos_flags |=
49                         QOS_PARAM_FLG_UPDATE_EDCA_MSK;
50
51         if (ctx->ht.enabled)
52                 ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
53
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);
57
58         iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
59                                sizeof(struct iwl_qosparam_cmd),
60                                &ctx->qos_data.def_qos_parm, NULL);
61 }
62
63 /**
64  * iwl_legacy_mac_config - mac80211 config callback
65  */
66 int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed)
67 {
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] = {};
79
80         if (WARN_ON(!priv->cfg->ops->legacy))
81                 return -EOPNOTSUPP;
82
83         mutex_lock(&priv->mutex);
84
85         IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
86                                         channel->hw_value, changed);
87
88         if (unlikely(test_bit(STATUS_SCANNING, &priv->status))) {
89                 scan_active = 1;
90                 IWL_DEBUG_MAC80211(priv, "scan active\n");
91         }
92
93         if (changed & (IEEE80211_CONF_CHANGE_SMPS |
94                        IEEE80211_CONF_CHANGE_CHANNEL)) {
95                 /* mac80211 uses static for non-HT which is what we want */
96                 priv->current_ht_config.smps = conf->smps_mode;
97
98                 /*
99                  * Recalculate chain counts.
100                  *
101                  * If monitor mode is enabled then mac80211 will
102                  * set up the SM PS mode to OFF if an HT channel is
103                  * configured.
104                  */
105                 if (priv->cfg->ops->hcmd->set_rxon_chain)
106                         for_each_context(priv, ctx)
107                                 priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
108         }
109
110         /* during scanning mac80211 will delay channel setting until
111          * scan finish with changed = 0
112          */
113         if (!changed || (changed & IEEE80211_CONF_CHANGE_CHANNEL)) {
114                 if (scan_active)
115                         goto set_ch_out;
116
117                 ch = channel->hw_value;
118                 ch_info = iwl_get_channel_info(priv, channel->band, ch);
119                 if (!is_channel_valid(ch_info)) {
120                         IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
121                         ret = -EINVAL;
122                         goto set_ch_out;
123                 }
124
125                 spin_lock_irqsave(&priv->lock, flags);
126
127                 for_each_context(priv, ctx) {
128                         /* Configure HT40 channels */
129                         if (ctx->ht.enabled != conf_is_ht(conf)) {
130                                 ctx->ht.enabled = conf_is_ht(conf);
131                                 ht_changed[ctx->ctxid] = true;
132                         }
133                         if (ctx->ht.enabled) {
134                                 if (conf_is_ht40_minus(conf)) {
135                                         ctx->ht.extension_chan_offset =
136                                                 IEEE80211_HT_PARAM_CHA_SEC_BELOW;
137                                         ctx->ht.is_40mhz = true;
138                                 } else if (conf_is_ht40_plus(conf)) {
139                                         ctx->ht.extension_chan_offset =
140                                                 IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
141                                         ctx->ht.is_40mhz = true;
142                                 } else {
143                                         ctx->ht.extension_chan_offset =
144                                                 IEEE80211_HT_PARAM_CHA_SEC_NONE;
145                                         ctx->ht.is_40mhz = false;
146                                 }
147                         } else
148                                 ctx->ht.is_40mhz = false;
149
150                         /*
151                          * Default to no protection. Protection mode will
152                          * later be set from BSS config in iwl_ht_conf
153                          */
154                         ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
155
156                         /* if we are switching from ht to 2.4 clear flags
157                          * from any ht related info since 2.4 does not
158                          * support ht */
159                         if ((le16_to_cpu(ctx->staging.channel) != ch))
160                                 ctx->staging.flags = 0;
161
162                         iwl_set_rxon_channel(priv, channel, ctx);
163                         iwl_set_rxon_ht(priv, ht_conf);
164
165                         iwl_set_flags_for_band(priv, ctx, channel->band,
166                                                ctx->vif);
167                 }
168
169                 spin_unlock_irqrestore(&priv->lock, flags);
170
171                 if (priv->cfg->ops->legacy->update_bcast_stations)
172                         ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
173
174  set_ch_out:
175                 /* The list of supported rates and rate mask can be different
176                  * for each band; since the band may have changed, reset
177                  * the rate mask to what mac80211 lists */
178                 iwl_set_rate(priv);
179         }
180
181         if (changed & (IEEE80211_CONF_CHANGE_PS |
182                         IEEE80211_CONF_CHANGE_IDLE)) {
183                 ret = iwl_power_update_mode(priv, false);
184                 if (ret)
185                         IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
186         }
187
188         if (changed & IEEE80211_CONF_CHANGE_POWER) {
189                 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
190                         priv->tx_power_user_lmt, conf->power_level);
191
192                 iwl_set_tx_power(priv, conf->power_level, false);
193         }
194
195         if (!iwl_is_ready(priv)) {
196                 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
197                 goto out;
198         }
199
200         if (scan_active)
201                 goto out;
202
203         for_each_context(priv, ctx) {
204                 if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
205                         iwlcore_commit_rxon(priv, ctx);
206                 else
207                         IWL_DEBUG_INFO(priv,
208                                 "Not re-sending same RXON configuration.\n");
209                 if (ht_changed[ctx->ctxid])
210                         iwl_update_qos(priv, ctx);
211         }
212
213 out:
214         IWL_DEBUG_MAC80211(priv, "leave\n");
215         mutex_unlock(&priv->mutex);
216         return ret;
217 }
218 EXPORT_SYMBOL(iwl_legacy_mac_config);
219
220 void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
221 {
222         struct iwl_priv *priv = hw->priv;
223         unsigned long flags;
224         /* IBSS can only be the IWL_RXON_CTX_BSS context */
225         struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
226
227         if (WARN_ON(!priv->cfg->ops->legacy))
228                 return;
229
230         mutex_lock(&priv->mutex);
231         IWL_DEBUG_MAC80211(priv, "enter\n");
232
233         spin_lock_irqsave(&priv->lock, flags);
234         memset(&priv->current_ht_config, 0, sizeof(struct iwl_ht_config));
235         spin_unlock_irqrestore(&priv->lock, flags);
236
237         spin_lock_irqsave(&priv->lock, flags);
238
239         /* new association get rid of ibss beacon skb */
240         if (priv->beacon_skb)
241                 dev_kfree_skb(priv->beacon_skb);
242
243         priv->beacon_skb = NULL;
244
245         priv->timestamp = 0;
246
247         spin_unlock_irqrestore(&priv->lock, flags);
248
249         iwl_scan_cancel_timeout(priv, 100);
250         if (!iwl_is_ready_rf(priv)) {
251                 IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
252                 mutex_unlock(&priv->mutex);
253                 return;
254         }
255
256         /* we are restarting association process
257          * clear RXON_FILTER_ASSOC_MSK bit
258          */
259         ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
260         iwlcore_commit_rxon(priv, ctx);
261
262         iwl_set_rate(priv);
263
264         mutex_unlock(&priv->mutex);
265
266         IWL_DEBUG_MAC80211(priv, "leave\n");
267 }
268 EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
269
270 static void iwl_ht_conf(struct iwl_priv *priv,
271                         struct ieee80211_vif *vif)
272 {
273         struct iwl_ht_config *ht_conf = &priv->current_ht_config;
274         struct ieee80211_sta *sta;
275         struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
276         struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
277
278         IWL_DEBUG_ASSOC(priv, "enter:\n");
279
280         if (!ctx->ht.enabled)
281                 return;
282
283         ctx->ht.protection =
284                 bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
285         ctx->ht.non_gf_sta_present =
286                 !!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
287
288         ht_conf->single_chain_sufficient = false;
289
290         switch (vif->type) {
291         case NL80211_IFTYPE_STATION:
292                 rcu_read_lock();
293                 sta = ieee80211_find_sta(vif, bss_conf->bssid);
294                 if (sta) {
295                         struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
296                         int maxstreams;
297
298                         maxstreams = (ht_cap->mcs.tx_params &
299                                       IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
300                                         >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
301                         maxstreams += 1;
302
303                         if ((ht_cap->mcs.rx_mask[1] == 0) &&
304                             (ht_cap->mcs.rx_mask[2] == 0))
305                                 ht_conf->single_chain_sufficient = true;
306                         if (maxstreams <= 1)
307                                 ht_conf->single_chain_sufficient = true;
308                 } else {
309                         /*
310                          * If at all, this can only happen through a race
311                          * when the AP disconnects us while we're still
312                          * setting up the connection, in that case mac80211
313                          * will soon tell us about that.
314                          */
315                         ht_conf->single_chain_sufficient = true;
316                 }
317                 rcu_read_unlock();
318                 break;
319         case NL80211_IFTYPE_ADHOC:
320                 ht_conf->single_chain_sufficient = true;
321                 break;
322         default:
323                 break;
324         }
325
326         IWL_DEBUG_ASSOC(priv, "leave\n");
327 }
328
329 static inline void iwl_set_no_assoc(struct iwl_priv *priv,
330                                     struct ieee80211_vif *vif)
331 {
332         struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
333
334         /*
335          * inform the ucode that there is no longer an
336          * association and that no more packets should be
337          * sent
338          */
339         ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
340         ctx->staging.assoc_id = 0;
341         iwlcore_commit_rxon(priv, ctx);
342 }
343
344 static void iwlcore_beacon_update(struct ieee80211_hw *hw,
345                                   struct ieee80211_vif *vif)
346 {
347         struct iwl_priv *priv = hw->priv;
348         unsigned long flags;
349         __le64 timestamp;
350         struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
351
352         if (!skb)
353                 return;
354
355         IWL_DEBUG_MAC80211(priv, "enter\n");
356
357         lockdep_assert_held(&priv->mutex);
358
359         if (!priv->beacon_ctx) {
360                 IWL_ERR(priv, "update beacon but no beacon context!\n");
361                 dev_kfree_skb(skb);
362                 return;
363         }
364
365         spin_lock_irqsave(&priv->lock, flags);
366
367         if (priv->beacon_skb)
368                 dev_kfree_skb(priv->beacon_skb);
369
370         priv->beacon_skb = skb;
371
372         timestamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
373         priv->timestamp = le64_to_cpu(timestamp);
374
375         IWL_DEBUG_MAC80211(priv, "leave\n");
376         spin_unlock_irqrestore(&priv->lock, flags);
377
378         if (!iwl_is_ready_rf(priv)) {
379                 IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
380                 return;
381         }
382
383         priv->cfg->ops->legacy->post_associate(priv);
384 }
385
386 void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
387                                      struct ieee80211_vif *vif,
388                                      struct ieee80211_bss_conf *bss_conf,
389                                      u32 changes)
390 {
391         struct iwl_priv *priv = hw->priv;
392         struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
393         int ret;
394
395         if (WARN_ON(!priv->cfg->ops->legacy))
396                 return;
397
398         IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
399
400         if (!iwl_is_alive(priv))
401                 return;
402
403         mutex_lock(&priv->mutex);
404
405         if (changes & BSS_CHANGED_QOS) {
406                 unsigned long flags;
407
408                 spin_lock_irqsave(&priv->lock, flags);
409                 ctx->qos_data.qos_active = bss_conf->qos;
410                 iwl_update_qos(priv, ctx);
411                 spin_unlock_irqrestore(&priv->lock, flags);
412         }
413
414         if (changes & BSS_CHANGED_BEACON_ENABLED) {
415                 /*
416                  * the add_interface code must make sure we only ever
417                  * have a single interface that could be beaconing at
418                  * any time.
419                  */
420                 if (vif->bss_conf.enable_beacon)
421                         priv->beacon_ctx = ctx;
422                 else
423                         priv->beacon_ctx = NULL;
424         }
425
426         if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
427                 dev_kfree_skb(priv->beacon_skb);
428                 priv->beacon_skb = ieee80211_beacon_get(hw, vif);
429         }
430
431         if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
432                 iwl_send_rxon_timing(priv, ctx);
433
434         if (changes & BSS_CHANGED_BSSID) {
435                 IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
436
437                 /*
438                  * If there is currently a HW scan going on in the
439                  * background then we need to cancel it else the RXON
440                  * below/in post_associate will fail.
441                  */
442                 if (iwl_scan_cancel_timeout(priv, 100)) {
443                         IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
444                         IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
445                         mutex_unlock(&priv->mutex);
446                         return;
447                 }
448
449                 /* mac80211 only sets assoc when in STATION mode */
450                 if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
451                         memcpy(ctx->staging.bssid_addr,
452                                bss_conf->bssid, ETH_ALEN);
453
454                         /* currently needed in a few places */
455                         memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
456                 } else {
457                         ctx->staging.filter_flags &=
458                                 ~RXON_FILTER_ASSOC_MSK;
459                 }
460
461         }
462
463         /*
464          * This needs to be after setting the BSSID in case
465          * mac80211 decides to do both changes at once because
466          * it will invoke post_associate.
467          */
468         if (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
469                 iwlcore_beacon_update(hw, vif);
470
471         if (changes & BSS_CHANGED_ERP_PREAMBLE) {
472                 IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
473                                    bss_conf->use_short_preamble);
474                 if (bss_conf->use_short_preamble)
475                         ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
476                 else
477                         ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
478         }
479
480         if (changes & BSS_CHANGED_ERP_CTS_PROT) {
481                 IWL_DEBUG_MAC80211(priv, "ERP_CTS %d\n", bss_conf->use_cts_prot);
482                 if (bss_conf->use_cts_prot && (priv->band != IEEE80211_BAND_5GHZ))
483                         ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
484                 else
485                         ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
486                 if (bss_conf->use_cts_prot)
487                         ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
488                 else
489                         ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
490         }
491
492         if (changes & BSS_CHANGED_BASIC_RATES) {
493                 /* XXX use this information
494                  *
495                  * To do that, remove code from iwl_set_rate() and put something
496                  * like this here:
497                  *
498                 if (A-band)
499                         ctx->staging.ofdm_basic_rates =
500                                 bss_conf->basic_rates;
501                 else
502                         ctx->staging.ofdm_basic_rates =
503                                 bss_conf->basic_rates >> 4;
504                         ctx->staging.cck_basic_rates =
505                                 bss_conf->basic_rates & 0xF;
506                  */
507         }
508
509         if (changes & BSS_CHANGED_HT) {
510                 iwl_ht_conf(priv, vif);
511
512                 if (priv->cfg->ops->hcmd->set_rxon_chain)
513                         priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
514         }
515
516         if (changes & BSS_CHANGED_ASSOC) {
517                 IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
518                 if (bss_conf->assoc) {
519                         priv->timestamp = bss_conf->timestamp;
520
521                         if (!iwl_is_rfkill(priv))
522                                 priv->cfg->ops->legacy->post_associate(priv);
523                 } else
524                         iwl_set_no_assoc(priv, vif);
525         }
526
527         if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
528                 IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
529                                    changes);
530                 ret = iwl_send_rxon_assoc(priv, ctx);
531                 if (!ret) {
532                         /* Sync active_rxon with latest change. */
533                         memcpy((void *)&ctx->active,
534                                 &ctx->staging,
535                                 sizeof(struct iwl_rxon_cmd));
536                 }
537         }
538
539         if (changes & BSS_CHANGED_BEACON_ENABLED) {
540                 if (vif->bss_conf.enable_beacon) {
541                         memcpy(ctx->staging.bssid_addr,
542                                bss_conf->bssid, ETH_ALEN);
543                         memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
544                         priv->cfg->ops->legacy->config_ap(priv);
545                 } else
546                         iwl_set_no_assoc(priv, vif);
547         }
548
549         if (changes & BSS_CHANGED_IBSS) {
550                 ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
551                                                         bss_conf->ibss_joined);
552                 if (ret)
553                         IWL_ERR(priv, "failed to %s IBSS station %pM\n",
554                                 bss_conf->ibss_joined ? "add" : "remove",
555                                 bss_conf->bssid);
556         }
557
558         mutex_unlock(&priv->mutex);
559
560         IWL_DEBUG_MAC80211(priv, "leave\n");
561 }
562 EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
563
564 irqreturn_t iwl_isr_legacy(int irq, void *data)
565 {
566         struct iwl_priv *priv = data;
567         u32 inta, inta_mask;
568         u32 inta_fh;
569         unsigned long flags;
570         if (!priv)
571                 return IRQ_NONE;
572
573         spin_lock_irqsave(&priv->lock, flags);
574
575         /* Disable (but don't clear!) interrupts here to avoid
576          *    back-to-back ISRs and sporadic interrupts from our NIC.
577          * If we have something to service, the tasklet will re-enable ints.
578          * If we *don't* have something, we'll re-enable before leaving here. */
579         inta_mask = iwl_read32(priv, CSR_INT_MASK);  /* just for debug */
580         iwl_write32(priv, CSR_INT_MASK, 0x00000000);
581
582         /* Discover which interrupts are active/pending */
583         inta = iwl_read32(priv, CSR_INT);
584         inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
585
586         /* Ignore interrupt if there's nothing in NIC to service.
587          * This may be due to IRQ shared with another device,
588          * or due to sporadic interrupts thrown from our NIC. */
589         if (!inta && !inta_fh) {
590                 IWL_DEBUG_ISR(priv,
591                         "Ignore interrupt, inta == 0, inta_fh == 0\n");
592                 goto none;
593         }
594
595         if ((inta == 0xFFFFFFFF) || ((inta & 0xFFFFFFF0) == 0xa5a5a5a0)) {
596                 /* Hardware disappeared. It might have already raised
597                  * an interrupt */
598                 IWL_WARN(priv, "HARDWARE GONE?? INTA == 0x%08x\n", inta);
599                 goto unplugged;
600         }
601
602         IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
603                       inta, inta_mask, inta_fh);
604
605         inta &= ~CSR_INT_BIT_SCD;
606
607         /* iwl_irq_tasklet() will service interrupts and re-enable them */
608         if (likely(inta || inta_fh))
609                 tasklet_schedule(&priv->irq_tasklet);
610
611 unplugged:
612         spin_unlock_irqrestore(&priv->lock, flags);
613         return IRQ_HANDLED;
614
615 none:
616         /* re-enable interrupts here since we don't have anything to service. */
617         /* only Re-enable if disabled by irq */
618         if (test_bit(STATUS_INT_ENABLED, &priv->status))
619                 iwl_enable_interrupts(priv);
620         spin_unlock_irqrestore(&priv->lock, flags);
621         return IRQ_NONE;
622 }
623 EXPORT_SYMBOL(iwl_isr_legacy);
624
625 /*
626  *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
627  *  function.
628  */
629 void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
630                                struct ieee80211_tx_info *info,
631                                __le16 fc, __le32 *tx_flags)
632 {
633         if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
634                 *tx_flags |= TX_CMD_FLG_RTS_MSK;
635                 *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
636                 *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
637
638                 if (!ieee80211_is_mgmt(fc))
639                         return;
640
641                 switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
642                 case cpu_to_le16(IEEE80211_STYPE_AUTH):
643                 case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
644                 case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
645                 case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
646                         *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
647                         *tx_flags |= TX_CMD_FLG_CTS_MSK;
648                         break;
649                 }
650         } else if (info->control.rates[0].flags &
651                    IEEE80211_TX_RC_USE_CTS_PROTECT) {
652                 *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
653                 *tx_flags |= TX_CMD_FLG_CTS_MSK;
654                 *tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
655         }
656 }
657 EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);