util.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2002-2005, Instant802 Networks, Inc.
00003  * Copyright 2005-2006, Devicescape Software, Inc.
00004  * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
00005  * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
00006  *
00007  * This program is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License version 2 as
00009  * published by the Free Software Foundation.
00010  *
00011  * utilities for mac80211
00012  */
00013 
00014 #include <net/mac80211.h>
00015 #include <linux/netdevice.h>
00016 #include <linux/export.h>
00017 #include <linux/types.h>
00018 #include <linux/slab.h>
00019 #include <linux/skbuff.h>
00020 #include <linux/etherdevice.h>
00021 #include <linux/if_arp.h>
00022 #include <linux/bitmap.h>
00023 #include <linux/crc32.h>
00024 #include <net/net_namespace.h>
00025 #include <net/cfg80211.h>
00026 #include <net/rtnetlink.h>
00027 
00028 #include "ieee80211_i.h"
00029 #include "driver-ops.h"
00030 #include "rate.h"
00031 #include "mesh.h"
00032 #include "wme.h"
00033 #include "led.h"
00034 #include "wep.h"
00035 
00036 /* privid for wiphys to determine whether they belong to us or not */
00037 void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
00038 
00039 struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
00040 {
00041         struct ieee80211_local *local;
00042         BUG_ON(!wiphy);
00043 
00044         local = wiphy_priv(wiphy);
00045         return &local->hw;
00046 }
00047 EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
00048 
00049 u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
00050                         enum nl80211_iftype type)
00051 {
00052         __le16 fc = hdr->frame_control;
00053 
00054          /* drop ACK/CTS frames and incorrect hdr len (ctrl) */
00055         if (len < 16)
00056                 return NULL;
00057 
00058         if (ieee80211_is_data(fc)) {
00059                 if (len < 24) /* drop incorrect hdr len (data) */
00060                         return NULL;
00061 
00062                 if (ieee80211_has_a4(fc))
00063                         return NULL;
00064                 if (ieee80211_has_tods(fc))
00065                         return hdr->addr1;
00066                 if (ieee80211_has_fromds(fc))
00067                         return hdr->addr2;
00068 
00069                 return hdr->addr3;
00070         }
00071 
00072         if (ieee80211_is_mgmt(fc)) {
00073                 if (len < 24) /* drop incorrect hdr len (mgmt) */
00074                         return NULL;
00075                 return hdr->addr3;
00076         }
00077 
00078         if (ieee80211_is_ctl(fc)) {
00079                 if(ieee80211_is_pspoll(fc))
00080                         return hdr->addr1;
00081 
00082                 if (ieee80211_is_back_req(fc)) {
00083                         switch (type) {
00084                         case NL80211_IFTYPE_STATION:
00085                                 return hdr->addr2;
00086                         case NL80211_IFTYPE_AP:
00087                         case NL80211_IFTYPE_AP_VLAN:
00088                                 return hdr->addr1;
00089                         default:
00090                                 break; /* fall through to the return */
00091                         }
00092                 }
00093         }
00094 
00095         return NULL;
00096 }
00097 
00098 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
00099 {
00100         struct sk_buff *skb;
00101         struct ieee80211_hdr *hdr;
00102 
00103         skb_queue_walk(&tx->skbs, skb) {
00104                 hdr = (struct ieee80211_hdr *) skb->data;
00105                 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
00106         }
00107 }
00108 
00109 int ieee80211_frame_duration(enum ieee80211_band band, size_t len,
00110                              int rate, int erp, int short_preamble)
00111 {
00112         int dur;
00113 
00114         /* calculate duration (in microseconds, rounded up to next higher
00115          * integer if it includes a fractional microsecond) to send frame of
00116          * len bytes (does not include FCS) at the given rate. Duration will
00117          * also include SIFS.
00118          *
00119          * rate is in 100 kbps, so divident is multiplied by 10 in the
00120          * DIV_ROUND_UP() operations.
00121          */
00122 
00123         if (band == IEEE80211_BAND_5GHZ || erp) {
00124                 /*
00125                  * OFDM:
00126                  *
00127                  * N_DBPS = DATARATE x 4
00128                  * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
00129                  *      (16 = SIGNAL time, 6 = tail bits)
00130                  * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
00131                  *
00132                  * T_SYM = 4 usec
00133                  * 802.11a - 17.5.2: aSIFSTime = 16 usec
00134                  * 802.11g - 19.8.4: aSIFSTime = 10 usec +
00135                  *      signal ext = 6 usec
00136                  */
00137                 dur = 16; /* SIFS + signal ext */
00138                 dur += 16; /* 17.3.2.3: T_PREAMBLE = 16 usec */
00139                 dur += 4; /* 17.3.2.3: T_SIGNAL = 4 usec */
00140                 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
00141                                         4 * rate); /* T_SYM x N_SYM */
00142         } else {
00143                 /*
00144                  * 802.11b or 802.11g with 802.11b compatibility:
00145                  * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
00146                  * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
00147                  *
00148                  * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
00149                  * aSIFSTime = 10 usec
00150                  * aPreambleLength = 144 usec or 72 usec with short preamble
00151                  * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
00152                  */
00153                 dur = 10; /* aSIFSTime = 10 usec */
00154                 dur += short_preamble ? (72 + 24) : (144 + 48);
00155 
00156                 dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
00157         }
00158 
00159         return dur;
00160 }
00161 
00162 /* Exported duration function for driver use */
00163 __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
00164                                         struct ieee80211_vif *vif,
00165                                         enum ieee80211_band band,
00166                                         size_t frame_len,
00167                                         struct ieee80211_rate *rate)
00168 {
00169         struct ieee80211_sub_if_data *sdata;
00170         u16 dur;
00171         int erp;
00172         bool short_preamble = false;
00173 
00174         erp = 0;
00175         if (vif) {
00176                 sdata = vif_to_sdata(vif);
00177                 short_preamble = sdata->vif.bss_conf.use_short_preamble;
00178                 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
00179                         erp = rate->flags & IEEE80211_RATE_ERP_G;
00180         }
00181 
00182         dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp,
00183                                        short_preamble);
00184 
00185         return cpu_to_le16(dur);
00186 }
00187 EXPORT_SYMBOL(ieee80211_generic_frame_duration);
00188 
00189 __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
00190                               struct ieee80211_vif *vif, size_t frame_len,
00191                               const struct ieee80211_tx_info *frame_txctl)
00192 {
00193         struct ieee80211_local *local = hw_to_local(hw);
00194         struct ieee80211_rate *rate;
00195         struct ieee80211_sub_if_data *sdata;
00196         bool short_preamble;
00197         int erp;
00198         u16 dur;
00199         struct ieee80211_supported_band *sband;
00200 
00201         sband = local->hw.wiphy->bands[frame_txctl->band];
00202 
00203         short_preamble = false;
00204 
00205         rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
00206 
00207         erp = 0;
00208         if (vif) {
00209                 sdata = vif_to_sdata(vif);
00210                 short_preamble = sdata->vif.bss_conf.use_short_preamble;
00211                 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
00212                         erp = rate->flags & IEEE80211_RATE_ERP_G;
00213         }
00214 
00215         /* CTS duration */
00216         dur = ieee80211_frame_duration(sband->band, 10, rate->bitrate,
00217                                        erp, short_preamble);
00218         /* Data frame duration */
00219         dur += ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
00220                                         erp, short_preamble);
00221         /* ACK duration */
00222         dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
00223                                         erp, short_preamble);
00224 
00225         return cpu_to_le16(dur);
00226 }
00227 EXPORT_SYMBOL(ieee80211_rts_duration);
00228 
00229 __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
00230                                     struct ieee80211_vif *vif,
00231                                     size_t frame_len,
00232                                     const struct ieee80211_tx_info *frame_txctl)
00233 {
00234         struct ieee80211_local *local = hw_to_local(hw);
00235         struct ieee80211_rate *rate;
00236         struct ieee80211_sub_if_data *sdata;
00237         bool short_preamble;
00238         int erp;
00239         u16 dur;
00240         struct ieee80211_supported_band *sband;
00241 
00242         sband = local->hw.wiphy->bands[frame_txctl->band];
00243 
00244         short_preamble = false;
00245 
00246         rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
00247         erp = 0;
00248         if (vif) {
00249                 sdata = vif_to_sdata(vif);
00250                 short_preamble = sdata->vif.bss_conf.use_short_preamble;
00251                 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
00252                         erp = rate->flags & IEEE80211_RATE_ERP_G;
00253         }
00254 
00255         /* Data frame duration */
00256         dur = ieee80211_frame_duration(sband->band, frame_len, rate->bitrate,
00257                                        erp, short_preamble);
00258         if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
00259                 /* ACK duration */
00260                 dur += ieee80211_frame_duration(sband->band, 10, rate->bitrate,
00261                                                 erp, short_preamble);
00262         }
00263 
00264         return cpu_to_le16(dur);
00265 }
00266 EXPORT_SYMBOL(ieee80211_ctstoself_duration);
00267 
00268 void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
00269 {
00270         struct ieee80211_sub_if_data *sdata;
00271         int n_acs = IEEE80211_NUM_ACS;
00272 
00273         if (local->hw.queues < IEEE80211_NUM_ACS)
00274                 n_acs = 1;
00275 
00276         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
00277                 int ac;
00278 
00279                 if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state))
00280                         continue;
00281 
00282                 if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
00283                     local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
00284                         continue;
00285 
00286                 for (ac = 0; ac < n_acs; ac++) {
00287                         int ac_queue = sdata->vif.hw_queue[ac];
00288 
00289                         if (ac_queue == queue ||
00290                             (sdata->vif.cab_queue == queue &&
00291                              local->queue_stop_reasons[ac_queue] == 0 &&
00292                              skb_queue_empty(&local->pending[ac_queue])))
00293                                 netif_wake_subqueue(sdata->dev, ac);
00294                 }
00295         }
00296 }
00297 
00298 static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
00299                                    enum queue_stop_reason reason)
00300 {
00301         struct ieee80211_local *local = hw_to_local(hw);
00302 
00303         trace_wake_queue(local, queue, reason);
00304 
00305         if (WARN_ON(queue >= hw->queues))
00306                 return;
00307 
00308         if (!test_bit(reason, &local->queue_stop_reasons[queue]))
00309                 return;
00310 
00311         __clear_bit(reason, &local->queue_stop_reasons[queue]);
00312 
00313         if (local->queue_stop_reasons[queue] != 0)
00314                 /* someone still has this queue stopped */
00315                 return;
00316 
00317         if (skb_queue_empty(&local->pending[queue])) {
00318                 rcu_read_lock();
00319                 ieee80211_propagate_queue_wake(local, queue);
00320                 rcu_read_unlock();
00321         } else
00322                 tasklet_schedule(&local->tx_pending_tasklet);
00323 }
00324 
00325 void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
00326                                     enum queue_stop_reason reason)
00327 {
00328         struct ieee80211_local *local = hw_to_local(hw);
00329         unsigned long flags;
00330 
00331         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00332         __ieee80211_wake_queue(hw, queue, reason);
00333         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00334 }
00335 
00336 void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
00337 {
00338         ieee80211_wake_queue_by_reason(hw, queue,
00339                                        IEEE80211_QUEUE_STOP_REASON_DRIVER);
00340 }
00341 EXPORT_SYMBOL(ieee80211_wake_queue);
00342 
00343 static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
00344                                    enum queue_stop_reason reason)
00345 {
00346         struct ieee80211_local *local = hw_to_local(hw);
00347         struct ieee80211_sub_if_data *sdata;
00348         int n_acs = IEEE80211_NUM_ACS;
00349 
00350         trace_stop_queue(local, queue, reason);
00351 
00352         if (WARN_ON(queue >= hw->queues))
00353                 return;
00354 
00355         if (test_bit(reason, &local->queue_stop_reasons[queue]))
00356                 return;
00357 
00358         __set_bit(reason, &local->queue_stop_reasons[queue]);
00359 
00360         if (local->hw.queues < IEEE80211_NUM_ACS)
00361                 n_acs = 1;
00362 
00363         rcu_read_lock();
00364         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
00365                 int ac;
00366 
00367                 for (ac = 0; ac < n_acs; ac++) {
00368                         if (sdata->vif.hw_queue[ac] == queue ||
00369                             sdata->vif.cab_queue == queue)
00370                                 netif_stop_subqueue(sdata->dev, ac);
00371                 }
00372         }
00373         rcu_read_unlock();
00374 }
00375 
00376 void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
00377                                     enum queue_stop_reason reason)
00378 {
00379         struct ieee80211_local *local = hw_to_local(hw);
00380         unsigned long flags;
00381 
00382         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00383         __ieee80211_stop_queue(hw, queue, reason);
00384         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00385 }
00386 
00387 void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
00388 {
00389         ieee80211_stop_queue_by_reason(hw, queue,
00390                                        IEEE80211_QUEUE_STOP_REASON_DRIVER);
00391 }
00392 EXPORT_SYMBOL(ieee80211_stop_queue);
00393 
00394 void ieee80211_add_pending_skb(struct ieee80211_local *local,
00395                                struct sk_buff *skb)
00396 {
00397         struct ieee80211_hw *hw = &local->hw;
00398         unsigned long flags;
00399         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00400         int queue = info->hw_queue;
00401 
00402         if (WARN_ON(!info->control.vif)) {
00403                 kfree_skb(skb);
00404                 return;
00405         }
00406 
00407         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00408         __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
00409         __skb_queue_tail(&local->pending[queue], skb);
00410         __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
00411         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00412 }
00413 
00414 void ieee80211_add_pending_skbs_fn(struct ieee80211_local *local,
00415                                    struct sk_buff_head *skbs,
00416                                    void (*fn)(void *data), void *data)
00417 {
00418         struct ieee80211_hw *hw = &local->hw;
00419         struct sk_buff *skb;
00420         unsigned long flags;
00421         int queue, i;
00422 
00423         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00424         while ((skb = skb_dequeue(skbs))) {
00425                 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
00426 
00427                 if (WARN_ON(!info->control.vif)) {
00428                         kfree_skb(skb);
00429                         continue;
00430                 }
00431 
00432                 queue = info->hw_queue;
00433 
00434                 __ieee80211_stop_queue(hw, queue,
00435                                 IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
00436 
00437                 __skb_queue_tail(&local->pending[queue], skb);
00438         }
00439 
00440         if (fn)
00441                 fn(data);
00442 
00443         for (i = 0; i < hw->queues; i++)
00444                 __ieee80211_wake_queue(hw, i,
00445                         IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
00446         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00447 }
00448 
00449 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
00450                                     enum queue_stop_reason reason)
00451 {
00452         struct ieee80211_local *local = hw_to_local(hw);
00453         unsigned long flags;
00454         int i;
00455 
00456         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00457 
00458         for (i = 0; i < hw->queues; i++)
00459                 __ieee80211_stop_queue(hw, i, reason);
00460 
00461         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00462 }
00463 
00464 void ieee80211_stop_queues(struct ieee80211_hw *hw)
00465 {
00466         ieee80211_stop_queues_by_reason(hw,
00467                                         IEEE80211_QUEUE_STOP_REASON_DRIVER);
00468 }
00469 EXPORT_SYMBOL(ieee80211_stop_queues);
00470 
00471 int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
00472 {
00473         struct ieee80211_local *local = hw_to_local(hw);
00474         unsigned long flags;
00475         int ret;
00476 
00477         if (WARN_ON(queue >= hw->queues))
00478                 return true;
00479 
00480         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00481         ret = !!local->queue_stop_reasons[queue];
00482         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00483         return ret;
00484 }
00485 EXPORT_SYMBOL(ieee80211_queue_stopped);
00486 
00487 void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
00488                                      enum queue_stop_reason reason)
00489 {
00490         struct ieee80211_local *local = hw_to_local(hw);
00491         unsigned long flags;
00492         int i;
00493 
00494         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
00495 
00496         for (i = 0; i < hw->queues; i++)
00497                 __ieee80211_wake_queue(hw, i, reason);
00498 
00499         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
00500 }
00501 
00502 void ieee80211_wake_queues(struct ieee80211_hw *hw)
00503 {
00504         ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER);
00505 }
00506 EXPORT_SYMBOL(ieee80211_wake_queues);
00507 
00508 void ieee80211_iterate_active_interfaces(
00509         struct ieee80211_hw *hw,
00510         void (*iterator)(void *data, u8 *mac,
00511                          struct ieee80211_vif *vif),
00512         void *data)
00513 {
00514         struct ieee80211_local *local = hw_to_local(hw);
00515         struct ieee80211_sub_if_data *sdata;
00516 
00517         mutex_lock(&local->iflist_mtx);
00518 
00519         list_for_each_entry(sdata, &local->interfaces, list) {
00520                 switch (sdata->vif.type) {
00521                 case NL80211_IFTYPE_MONITOR:
00522                 case NL80211_IFTYPE_AP_VLAN:
00523                         continue;
00524                 default:
00525                         break;
00526                 }
00527                 if (ieee80211_sdata_running(sdata))
00528                         iterator(data, sdata->vif.addr,
00529                                  &sdata->vif);
00530         }
00531 
00532         mutex_unlock(&local->iflist_mtx);
00533 }
00534 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces);
00535 
00536 void ieee80211_iterate_active_interfaces_atomic(
00537         struct ieee80211_hw *hw,
00538         void (*iterator)(void *data, u8 *mac,
00539                          struct ieee80211_vif *vif),
00540         void *data)
00541 {
00542         struct ieee80211_local *local = hw_to_local(hw);
00543         struct ieee80211_sub_if_data *sdata;
00544 
00545         rcu_read_lock();
00546 
00547         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
00548                 switch (sdata->vif.type) {
00549                 case NL80211_IFTYPE_MONITOR:
00550                 case NL80211_IFTYPE_AP_VLAN:
00551                         continue;
00552                 default:
00553                         break;
00554                 }
00555                 if (ieee80211_sdata_running(sdata))
00556                         iterator(data, sdata->vif.addr,
00557                                  &sdata->vif);
00558         }
00559 
00560         rcu_read_unlock();
00561 }
00562 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
00563 
00564 /*
00565  * Nothing should have been stuffed into the workqueue during
00566  * the suspend->resume cycle. If this WARN is seen then there
00567  * is a bug with either the driver suspend or something in
00568  * mac80211 stuffing into the workqueue which we haven't yet
00569  * cleared during mac80211's suspend cycle.
00570  */
00571 static bool ieee80211_can_queue_work(struct ieee80211_local *local)
00572 {
00573         if (WARN(local->suspended && !local->resuming,
00574                  "queueing ieee80211 work while going to suspend\n"))
00575                 return false;
00576 
00577         return true;
00578 }
00579 
00580 void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
00581 {
00582         struct ieee80211_local *local = hw_to_local(hw);
00583 
00584         if (!ieee80211_can_queue_work(local))
00585                 return;
00586 
00587         queue_work(local->workqueue, work);
00588 }
00589 EXPORT_SYMBOL(ieee80211_queue_work);
00590 
00591 void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
00592                                   struct delayed_work *dwork,
00593                                   unsigned long delay)
00594 {
00595         struct ieee80211_local *local = hw_to_local(hw);
00596 
00597         if (!ieee80211_can_queue_work(local))
00598                 return;
00599 
00600         queue_delayed_work(local->workqueue, dwork, delay);
00601 }
00602 EXPORT_SYMBOL(ieee80211_queue_delayed_work);
00603 
00604 u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
00605                                struct ieee802_11_elems *elems,
00606                                u64 filter, u32 crc)
00607 {
00608         size_t left = len;
00609         u8 *pos = start;
00610         bool calc_crc = filter != 0;
00611         DECLARE_BITMAP(seen_elems, 256);
00612 
00613         bitmap_zero(seen_elems, 256);
00614         memset(elems, 0, sizeof(*elems));
00615         elems->ie_start = start;
00616         elems->total_len = len;
00617 
00618         while (left >= 2) {
00619                 u8 id, elen;
00620                 bool elem_parse_failed;
00621 
00622                 id = *pos++;
00623                 elen = *pos++;
00624                 left -= 2;
00625 
00626                 if (elen > left) {
00627                         elems->parse_error = true;
00628                         break;
00629                 }
00630 
00631                 if (id != WLAN_EID_VENDOR_SPECIFIC &&
00632                     id != WLAN_EID_QUIET &&
00633                     test_bit(id, seen_elems)) {
00634                         elems->parse_error = true;
00635                         left -= elen;
00636                         pos += elen;
00637                         continue;
00638                 }
00639 
00640                 if (calc_crc && id < 64 && (filter & (1ULL << id)))
00641                         crc = crc32_be(crc, pos - 2, elen + 2);
00642 
00643                 elem_parse_failed = false;
00644 
00645                 switch (id) {
00646                 case WLAN_EID_SSID:
00647                         elems->ssid = pos;
00648                         elems->ssid_len = elen;
00649                         break;
00650                 case WLAN_EID_SUPP_RATES:
00651                         elems->supp_rates = pos;
00652                         elems->supp_rates_len = elen;
00653                         break;
00654                 case WLAN_EID_FH_PARAMS:
00655                         elems->fh_params = pos;
00656                         elems->fh_params_len = elen;
00657                         break;
00658                 case WLAN_EID_DS_PARAMS:
00659                         elems->ds_params = pos;
00660                         elems->ds_params_len = elen;
00661                         break;
00662                 case WLAN_EID_CF_PARAMS:
00663                         elems->cf_params = pos;
00664                         elems->cf_params_len = elen;
00665                         break;
00666                 case WLAN_EID_TIM:
00667                         if (elen >= sizeof(struct ieee80211_tim_ie)) {
00668                                 elems->tim = (void *)pos;
00669                                 elems->tim_len = elen;
00670                         } else
00671                                 elem_parse_failed = true;
00672                         break;
00673                 case WLAN_EID_IBSS_PARAMS:
00674                         elems->ibss_params = pos;
00675                         elems->ibss_params_len = elen;
00676                         break;
00677                 case WLAN_EID_CHALLENGE:
00678                         elems->challenge = pos;
00679                         elems->challenge_len = elen;
00680                         break;
00681                 case WLAN_EID_VENDOR_SPECIFIC:
00682                         if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
00683                             pos[2] == 0xf2) {
00684                                 /* Microsoft OUI (00:50:F2) */
00685 
00686                                 if (calc_crc)
00687                                         crc = crc32_be(crc, pos - 2, elen + 2);
00688 
00689                                 if (pos[3] == 1) {
00690                                         /* OUI Type 1 - WPA IE */
00691                                         elems->wpa = pos;
00692                                         elems->wpa_len = elen;
00693                                 } else if (elen >= 5 && pos[3] == 2) {
00694                                         /* OUI Type 2 - WMM IE */
00695                                         if (pos[4] == 0) {
00696                                                 elems->wmm_info = pos;
00697                                                 elems->wmm_info_len = elen;
00698                                         } else if (pos[4] == 1) {
00699                                                 elems->wmm_param = pos;
00700                                                 elems->wmm_param_len = elen;
00701                                         }
00702                                 }
00703                         }
00704                         break;
00705                 case WLAN_EID_RSN:
00706                         elems->rsn = pos;
00707                         elems->rsn_len = elen;
00708                         break;
00709                 case WLAN_EID_ERP_INFO:
00710                         elems->erp_info = pos;
00711                         elems->erp_info_len = elen;
00712                         break;
00713                 case WLAN_EID_EXT_SUPP_RATES:
00714                         elems->ext_supp_rates = pos;
00715                         elems->ext_supp_rates_len = elen;
00716                         break;
00717                 case WLAN_EID_HT_CAPABILITY:
00718                         if (elen >= sizeof(struct ieee80211_ht_cap))
00719                                 elems->ht_cap_elem = (void *)pos;
00720                         else
00721                                 elem_parse_failed = true;
00722                         break;
00723                 case WLAN_EID_HT_OPERATION:
00724                         if (elen >= sizeof(struct ieee80211_ht_operation))
00725                                 elems->ht_operation = (void *)pos;
00726                         else
00727                                 elem_parse_failed = true;
00728                         break;
00729                 case WLAN_EID_MESH_ID:
00730                         elems->mesh_id = pos;
00731                         elems->mesh_id_len = elen;
00732                         break;
00733                 case WLAN_EID_MESH_CONFIG:
00734                         if (elen >= sizeof(struct ieee80211_meshconf_ie))
00735                                 elems->mesh_config = (void *)pos;
00736                         else
00737                                 elem_parse_failed = true;
00738                         break;
00739                 case WLAN_EID_PEER_MGMT:
00740                         elems->peering = pos;
00741                         elems->peering_len = elen;
00742                         break;
00743                 case WLAN_EID_PREQ:
00744                         elems->preq = pos;
00745                         elems->preq_len = elen;
00746                         break;
00747                 case WLAN_EID_PREP:
00748                         elems->prep = pos;
00749                         elems->prep_len = elen;
00750                         break;
00751                 case WLAN_EID_PERR:
00752                         elems->perr = pos;
00753                         elems->perr_len = elen;
00754                         break;
00755                 case WLAN_EID_RANN:
00756                         if (elen >= sizeof(struct ieee80211_rann_ie))
00757                                 elems->rann = (void *)pos;
00758                         else
00759                                 elem_parse_failed = true;
00760                         break;
00761                 case WLAN_EID_CHANNEL_SWITCH:
00762                         elems->ch_switch_elem = pos;
00763                         elems->ch_switch_elem_len = elen;
00764                         break;
00765                 case WLAN_EID_QUIET:
00766                         if (!elems->quiet_elem) {
00767                                 elems->quiet_elem = pos;
00768                                 elems->quiet_elem_len = elen;
00769                         }
00770                         elems->num_of_quiet_elem++;
00771                         break;
00772                 case WLAN_EID_COUNTRY:
00773                         elems->country_elem = pos;
00774                         elems->country_elem_len = elen;
00775                         break;
00776                 case WLAN_EID_PWR_CONSTRAINT:
00777                         elems->pwr_constr_elem = pos;
00778                         elems->pwr_constr_elem_len = elen;
00779                         break;
00780                 case WLAN_EID_TIMEOUT_INTERVAL:
00781                         elems->timeout_int = pos;
00782                         elems->timeout_int_len = elen;
00783                         break;
00784                 default:
00785                         break;
00786                 }
00787 
00788                 if (elem_parse_failed)
00789                         elems->parse_error = true;
00790                 else
00791                         set_bit(id, seen_elems);
00792 
00793                 left -= elen;
00794                 pos += elen;
00795         }
00796 
00797         if (left != 0)
00798                 elems->parse_error = true;
00799 
00800         return crc;
00801 }
00802 
00803 void ieee802_11_parse_elems(u8 *start, size_t len,
00804                             struct ieee802_11_elems *elems)
00805 {
00806         ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
00807 }
00808 
00809 void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
00810                                bool bss_notify)
00811 {
00812         struct ieee80211_local *local = sdata->local;
00813         struct ieee80211_tx_queue_params qparam;
00814         int ac;
00815         bool use_11b;
00816         int aCWmin, aCWmax;
00817 
00818         if (!local->ops->conf_tx)
00819                 return;
00820 
00821         if (local->hw.queues < IEEE80211_NUM_ACS)
00822                 return;
00823 
00824         memset(&qparam, 0, sizeof(qparam));
00825 
00826         use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) &&
00827                  !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
00828 
00829         for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
00830                 /* Set defaults according to 802.11-2007 Table 7-37 */
00831                 aCWmax = 1023;
00832                 if (use_11b)
00833                         aCWmin = 31;
00834                 else
00835                         aCWmin = 15;
00836 
00837                 switch (ac) {
00838                 case IEEE80211_AC_BK:
00839                         qparam.cw_max = aCWmax;
00840                         qparam.cw_min = aCWmin;
00841                         qparam.txop = 0;
00842                         qparam.aifs = 7;
00843                         break;
00844                 default: /* never happens but let's not leave undefined */
00845                 case IEEE80211_AC_BE:
00846                         qparam.cw_max = aCWmax;
00847                         qparam.cw_min = aCWmin;
00848                         qparam.txop = 0;
00849                         qparam.aifs = 3;
00850                         break;
00851                 case IEEE80211_AC_VI:
00852                         qparam.cw_max = aCWmin;
00853                         qparam.cw_min = (aCWmin + 1) / 2 - 1;
00854                         if (use_11b)
00855                                 qparam.txop = 6016/32;
00856                         else
00857                                 qparam.txop = 3008/32;
00858                         qparam.aifs = 2;
00859                         break;
00860                 case IEEE80211_AC_VO:
00861                         qparam.cw_max = (aCWmin + 1) / 2 - 1;
00862                         qparam.cw_min = (aCWmin + 1) / 4 - 1;
00863                         if (use_11b)
00864                                 qparam.txop = 3264/32;
00865                         else
00866                                 qparam.txop = 1504/32;
00867                         qparam.aifs = 2;
00868                         break;
00869                 }
00870 
00871                 qparam.uapsd = false;
00872 
00873                 sdata->tx_conf[ac] = qparam;
00874                 drv_conf_tx(local, sdata, ac, &qparam);
00875         }
00876 
00877         /* after reinitialize QoS TX queues setting to default,
00878          * disable QoS at all */
00879 
00880         if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
00881                 sdata->vif.bss_conf.qos =
00882                         sdata->vif.type != NL80211_IFTYPE_STATION;
00883                 if (bss_notify)
00884                         ieee80211_bss_info_change_notify(sdata,
00885                                                          BSS_CHANGED_QOS);
00886         }
00887 }
00888 
00889 void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
00890                                   const size_t supp_rates_len,
00891                                   const u8 *supp_rates)
00892 {
00893         struct ieee80211_local *local = sdata->local;
00894         int i, have_higher_than_11mbit = 0;
00895 
00896         /* cf. IEEE 802.11 9.2.12 */
00897         for (i = 0; i < supp_rates_len; i++)
00898                 if ((supp_rates[i] & 0x7f) * 5 > 110)
00899                         have_higher_than_11mbit = 1;
00900 
00901         if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
00902             have_higher_than_11mbit)
00903                 sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE;
00904         else
00905                 sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE;
00906 
00907         ieee80211_set_wmm_default(sdata, true);
00908 }
00909 
00910 u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
00911                               enum ieee80211_band band)
00912 {
00913         struct ieee80211_supported_band *sband;
00914         struct ieee80211_rate *bitrates;
00915         u32 mandatory_rates;
00916         enum ieee80211_rate_flags mandatory_flag;
00917         int i;
00918 
00919         sband = local->hw.wiphy->bands[band];
00920         if (WARN_ON(!sband))
00921                 return 1;
00922 
00923         if (band == IEEE80211_BAND_2GHZ)
00924                 mandatory_flag = IEEE80211_RATE_MANDATORY_B;
00925         else
00926                 mandatory_flag = IEEE80211_RATE_MANDATORY_A;
00927 
00928         bitrates = sband->bitrates;
00929         mandatory_rates = 0;
00930         for (i = 0; i < sband->n_bitrates; i++)
00931                 if (bitrates[i].flags & mandatory_flag)
00932                         mandatory_rates |= BIT(i);
00933         return mandatory_rates;
00934 }
00935 
00936 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
00937                          u16 transaction, u16 auth_alg,
00938                          u8 *extra, size_t extra_len, const u8 *da,
00939                          const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx)
00940 {
00941         struct ieee80211_local *local = sdata->local;
00942         struct sk_buff *skb;
00943         struct ieee80211_mgmt *mgmt;
00944         int err;
00945 
00946         skb = dev_alloc_skb(local->hw.extra_tx_headroom +
00947                             sizeof(*mgmt) + 6 + extra_len);
00948         if (!skb)
00949                 return;
00950 
00951         skb_reserve(skb, local->hw.extra_tx_headroom);
00952 
00953         mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24 + 6);
00954         memset(mgmt, 0, 24 + 6);
00955         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
00956                                           IEEE80211_STYPE_AUTH);
00957         memcpy(mgmt->da, da, ETH_ALEN);
00958         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
00959         memcpy(mgmt->bssid, bssid, ETH_ALEN);
00960         mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
00961         mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
00962         mgmt->u.auth.status_code = cpu_to_le16(0);
00963         if (extra)
00964                 memcpy(skb_put(skb, extra_len), extra, extra_len);
00965 
00966         if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
00967                 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
00968                 err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
00969                 WARN_ON(err);
00970         }
00971 
00972         IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
00973         ieee80211_tx_skb(sdata, skb);
00974 }
00975 
00976 int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
00977                              const u8 *ie, size_t ie_len,
00978                              enum ieee80211_band band, u32 rate_mask,
00979                              u8 channel)
00980 {
00981         struct ieee80211_supported_band *sband;
00982         u8 *pos;
00983         size_t offset = 0, noffset;
00984         int supp_rates_len, i;
00985         u8 rates[32];
00986         int num_rates;
00987         int ext_rates_len;
00988 
00989         sband = local->hw.wiphy->bands[band];
00990 
00991         pos = buffer;
00992 
00993         num_rates = 0;
00994         for (i = 0; i < sband->n_bitrates; i++) {
00995                 if ((BIT(i) & rate_mask) == 0)
00996                         continue; /* skip rate */
00997                 rates[num_rates++] = (u8) (sband->bitrates[i].bitrate / 5);
00998         }
00999 
01000         supp_rates_len = min_t(int, num_rates, 8);
01001 
01002         *pos++ = WLAN_EID_SUPP_RATES;
01003         *pos++ = supp_rates_len;
01004         memcpy(pos, rates, supp_rates_len);
01005         pos += supp_rates_len;
01006 
01007         /* insert "request information" if in custom IEs */
01008         if (ie && ie_len) {
01009                 static const u8 before_extrates[] = {
01010                         WLAN_EID_SSID,
01011                         WLAN_EID_SUPP_RATES,
01012                         WLAN_EID_REQUEST,
01013                 };
01014                 noffset = ieee80211_ie_split(ie, ie_len,
01015                                              before_extrates,
01016                                              ARRAY_SIZE(before_extrates),
01017                                              offset);
01018                 memcpy(pos, ie + offset, noffset - offset);
01019                 pos += noffset - offset;
01020                 offset = noffset;
01021         }
01022 
01023         ext_rates_len = num_rates - supp_rates_len;
01024         if (ext_rates_len > 0) {
01025                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
01026                 *pos++ = ext_rates_len;
01027                 memcpy(pos, rates + supp_rates_len, ext_rates_len);
01028                 pos += ext_rates_len;
01029         }
01030 
01031         if (channel && sband->band == IEEE80211_BAND_2GHZ) {
01032                 *pos++ = WLAN_EID_DS_PARAMS;
01033                 *pos++ = 1;
01034                 *pos++ = channel;
01035         }
01036 
01037         /* insert custom IEs that go before HT */
01038         if (ie && ie_len) {
01039                 static const u8 before_ht[] = {
01040                         WLAN_EID_SSID,
01041                         WLAN_EID_SUPP_RATES,
01042                         WLAN_EID_REQUEST,
01043                         WLAN_EID_EXT_SUPP_RATES,
01044                         WLAN_EID_DS_PARAMS,
01045                         WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
01046                 };
01047                 noffset = ieee80211_ie_split(ie, ie_len,
01048                                              before_ht, ARRAY_SIZE(before_ht),
01049                                              offset);
01050                 memcpy(pos, ie + offset, noffset - offset);
01051                 pos += noffset - offset;
01052                 offset = noffset;
01053         }
01054 
01055         if (sband->ht_cap.ht_supported)
01056                 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
01057                                                 sband->ht_cap.cap);
01058 
01059         /*
01060          * If adding more here, adjust code in main.c
01061          * that calculates local->scan_ies_len.
01062          */
01063 
01064         /* add any remaining custom IEs */
01065         if (ie && ie_len) {
01066                 noffset = ie_len;
01067                 memcpy(pos, ie + offset, noffset - offset);
01068                 pos += noffset - offset;
01069         }
01070 
01071         return pos - buffer;
01072 }
01073 
01074 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
01075                                           u8 *dst, u32 ratemask,
01076                                           const u8 *ssid, size_t ssid_len,
01077                                           const u8 *ie, size_t ie_len,
01078                                           bool directed)
01079 {
01080         struct ieee80211_local *local = sdata->local;
01081         struct sk_buff *skb;
01082         struct ieee80211_mgmt *mgmt;
01083         size_t buf_len;
01084         u8 *buf;
01085         u8 chan;
01086 
01087         /* FIXME: come up with a proper value */
01088         buf = kmalloc(200 + ie_len, GFP_KERNEL);
01089         if (!buf)
01090                 return NULL;
01091 
01092         /*
01093          * Do not send DS Channel parameter for directed probe requests
01094          * in order to maximize the chance that we get a response.  Some
01095          * badly-behaved APs don't respond when this parameter is included.
01096          */
01097         if (directed)
01098                 chan = 0;
01099         else
01100                 chan = ieee80211_frequency_to_channel(
01101                         local->hw.conf.channel->center_freq);
01102 
01103         buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
01104                                            local->hw.conf.channel->band,
01105                                            ratemask, chan);
01106 
01107         skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
01108                                      ssid, ssid_len,
01109                                      buf, buf_len);
01110         if (!skb)
01111                 goto out;
01112 
01113         if (dst) {
01114                 mgmt = (struct ieee80211_mgmt *) skb->data;
01115                 memcpy(mgmt->da, dst, ETH_ALEN);
01116                 memcpy(mgmt->bssid, dst, ETH_ALEN);
01117         }
01118 
01119         IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
01120 
01121  out:
01122         kfree(buf);
01123 
01124         return skb;
01125 }
01126 
01127 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
01128                               const u8 *ssid, size_t ssid_len,
01129                               const u8 *ie, size_t ie_len,
01130                               u32 ratemask, bool directed, bool no_cck)
01131 {
01132         struct sk_buff *skb;
01133 
01134         skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len,
01135                                         ie, ie_len, directed);
01136         if (skb) {
01137                 if (no_cck)
01138                         IEEE80211_SKB_CB(skb)->flags |=
01139                                 IEEE80211_TX_CTL_NO_CCK_RATE;
01140                 ieee80211_tx_skb(sdata, skb);
01141         }
01142 }
01143 
01144 u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
01145                             struct ieee802_11_elems *elems,
01146                             enum ieee80211_band band, u32 *basic_rates)
01147 {
01148         struct ieee80211_supported_band *sband;
01149         struct ieee80211_rate *bitrates;
01150         size_t num_rates;
01151         u32 supp_rates;
01152         int i, j;
01153         sband = local->hw.wiphy->bands[band];
01154 
01155         if (WARN_ON(!sband))
01156                 return 1;
01157 
01158         bitrates = sband->bitrates;
01159         num_rates = sband->n_bitrates;
01160         supp_rates = 0;
01161         for (i = 0; i < elems->supp_rates_len +
01162                      elems->ext_supp_rates_len; i++) {
01163                 u8 rate = 0;
01164                 int own_rate;
01165                 bool is_basic;
01166                 if (i < elems->supp_rates_len)
01167                         rate = elems->supp_rates[i];
01168                 else if (elems->ext_supp_rates)
01169                         rate = elems->ext_supp_rates
01170                                 [i - elems->supp_rates_len];
01171                 own_rate = 5 * (rate & 0x7f);
01172                 is_basic = !!(rate & 0x80);
01173 
01174                 if (is_basic && (rate & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
01175                         continue;
01176 
01177                 for (j = 0; j < num_rates; j++) {
01178                         if (bitrates[j].bitrate == own_rate) {
01179                                 supp_rates |= BIT(j);
01180                                 if (basic_rates && is_basic)
01181                                         *basic_rates |= BIT(j);
01182                         }
01183                 }
01184         }
01185         return supp_rates;
01186 }
01187 
01188 void ieee80211_stop_device(struct ieee80211_local *local)
01189 {
01190         ieee80211_led_radio(local, false);
01191         ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO);
01192 
01193         cancel_work_sync(&local->reconfig_filter);
01194 
01195         flush_workqueue(local->workqueue);
01196         drv_stop(local);
01197 }
01198 
01199 int ieee80211_reconfig(struct ieee80211_local *local)
01200 {
01201         struct ieee80211_hw *hw = &local->hw;
01202         struct ieee80211_sub_if_data *sdata;
01203         struct sta_info *sta;
01204         int res, i;
01205 
01206 #ifdef CONFIG_PM
01207         if (local->suspended)
01208                 local->resuming = true;
01209 
01210         if (local->wowlan) {
01211                 local->wowlan = false;
01212                 res = drv_resume(local);
01213                 if (res < 0) {
01214                         local->resuming = false;
01215                         return res;
01216                 }
01217                 if (res == 0)
01218                         goto wake_up;
01219                 WARN_ON(res > 1);
01220                 /*
01221                  * res is 1, which means the driver requested
01222                  * to go through a regular reset on wakeup.
01223                  */
01224         }
01225 #endif
01226         /* everything else happens only if HW was up & running */
01227         if (!local->open_count)
01228                 goto wake_up;
01229 
01230         /*
01231          * Upon resume hardware can sometimes be goofy due to
01232          * various platform / driver / bus issues, so restarting
01233          * the device may at times not work immediately. Propagate
01234          * the error.
01235          */
01236         res = drv_start(local);
01237         if (res) {
01238                 WARN(local->suspended, "Hardware became unavailable "
01239                      "upon resume. This could be a software issue "
01240                      "prior to suspend or a hardware issue.\n");
01241                 return res;
01242         }
01243 
01244         /* setup fragmentation threshold */
01245         drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
01246 
01247         /* setup RTS threshold */
01248         drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
01249 
01250         /* reset coverage class */
01251         drv_set_coverage_class(local, hw->wiphy->coverage_class);
01252 
01253         ieee80211_led_radio(local, true);
01254         ieee80211_mod_tpt_led_trig(local,
01255                                    IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
01256 
01257         /* add interfaces */
01258         sdata = rtnl_dereference(local->monitor_sdata);
01259         if (sdata) {
01260                 res = drv_add_interface(local, sdata);
01261                 if (WARN_ON(res)) {
01262                         rcu_assign_pointer(local->monitor_sdata, NULL);
01263                         synchronize_net();
01264                         kfree(sdata);
01265                 }
01266         }
01267 
01268         list_for_each_entry(sdata, &local->interfaces, list) {
01269                 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
01270                     sdata->vif.type != NL80211_IFTYPE_MONITOR &&
01271                     ieee80211_sdata_running(sdata))
01272                         res = drv_add_interface(local, sdata);
01273         }
01274 
01275         /* add STAs back */
01276         mutex_lock(&local->sta_mtx);
01277         list_for_each_entry(sta, &local->sta_list, list) {
01278                 if (sta->uploaded) {
01279                         enum ieee80211_sta_state state;
01280 
01281                         for (state = IEEE80211_STA_NOTEXIST;
01282                              state < sta->sta_state; state++)
01283                                 WARN_ON(drv_sta_state(local, sta->sdata, sta,
01284                                                       state, state + 1));
01285                 }
01286         }
01287         mutex_unlock(&local->sta_mtx);
01288 
01289         /* reconfigure tx conf */
01290         if (hw->queues >= IEEE80211_NUM_ACS) {
01291                 list_for_each_entry(sdata, &local->interfaces, list) {
01292                         if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
01293                             sdata->vif.type == NL80211_IFTYPE_MONITOR ||
01294                             !ieee80211_sdata_running(sdata))
01295                                 continue;
01296 
01297                         for (i = 0; i < IEEE80211_NUM_ACS; i++)
01298                                 drv_conf_tx(local, sdata, i,
01299                                             &sdata->tx_conf[i]);
01300                 }
01301         }
01302 
01303         /* reconfigure hardware */
01304         ieee80211_hw_config(local, ~0);
01305 
01306         ieee80211_configure_filter(local);
01307 
01308         /* Finally also reconfigure all the BSS information */
01309         list_for_each_entry(sdata, &local->interfaces, list) {
01310                 u32 changed;
01311 
01312                 if (!ieee80211_sdata_running(sdata))
01313                         continue;
01314 
01315                 /* common change flags for all interface types */
01316                 changed = BSS_CHANGED_ERP_CTS_PROT |
01317                           BSS_CHANGED_ERP_PREAMBLE |
01318                           BSS_CHANGED_ERP_SLOT |
01319                           BSS_CHANGED_HT |
01320                           BSS_CHANGED_BASIC_RATES |
01321                           BSS_CHANGED_BEACON_INT |
01322                           BSS_CHANGED_BSSID |
01323                           BSS_CHANGED_CQM |
01324                           BSS_CHANGED_QOS |
01325                           BSS_CHANGED_IDLE;
01326 
01327                 switch (sdata->vif.type) {
01328                 case NL80211_IFTYPE_STATION:
01329                         changed |= BSS_CHANGED_ASSOC |
01330                                    BSS_CHANGED_ARP_FILTER;
01331                         mutex_lock(&sdata->u.mgd.mtx);
01332                         ieee80211_bss_info_change_notify(sdata, changed);
01333                         mutex_unlock(&sdata->u.mgd.mtx);
01334                         break;
01335                 case NL80211_IFTYPE_ADHOC:
01336                         changed |= BSS_CHANGED_IBSS;
01337                         /* fall through */
01338                 case NL80211_IFTYPE_AP:
01339                         changed |= BSS_CHANGED_SSID;
01340 
01341                         if (sdata->vif.type == NL80211_IFTYPE_AP)
01342                                 changed |= BSS_CHANGED_AP_PROBE_RESP;
01343 
01344                         /* fall through */
01345                 case NL80211_IFTYPE_MESH_POINT:
01346                         changed |= BSS_CHANGED_BEACON |
01347                                    BSS_CHANGED_BEACON_ENABLED;
01348                         ieee80211_bss_info_change_notify(sdata, changed);
01349                         break;
01350                 case NL80211_IFTYPE_WDS:
01351                         break;
01352                 case NL80211_IFTYPE_AP_VLAN:
01353                 case NL80211_IFTYPE_MONITOR:
01354                         /* ignore virtual */
01355                         break;
01356                 case NL80211_IFTYPE_UNSPECIFIED:
01357                 case NUM_NL80211_IFTYPES:
01358                 case NL80211_IFTYPE_P2P_CLIENT:
01359                 case NL80211_IFTYPE_P2P_GO:
01360                         WARN_ON(1);
01361                         break;
01362                 }
01363         }
01364 
01365         ieee80211_recalc_ps(local, -1);
01366 
01367         /*
01368          * The sta might be in psm against the ap (e.g. because
01369          * this was the state before a hw restart), so we
01370          * explicitly send a null packet in order to make sure
01371          * it'll sync against the ap (and get out of psm).
01372          */
01373         if (!(local->hw.conf.flags & IEEE80211_CONF_PS)) {
01374                 list_for_each_entry(sdata, &local->interfaces, list) {
01375                         if (sdata->vif.type != NL80211_IFTYPE_STATION)
01376                                 continue;
01377 
01378                         ieee80211_send_nullfunc(local, sdata, 0);
01379                 }
01380         }
01381 
01382         /* add back keys */
01383         list_for_each_entry(sdata, &local->interfaces, list)
01384                 if (ieee80211_sdata_running(sdata))
01385                         ieee80211_enable_keys(sdata);
01386 
01387  wake_up:
01388         /*
01389          * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
01390          * sessions can be established after a resume.
01391          *
01392          * Also tear down aggregation sessions since reconfiguring
01393          * them in a hardware restart scenario is not easily done
01394          * right now, and the hardware will have lost information
01395          * about the sessions, but we and the AP still think they
01396          * are active. This is really a workaround though.
01397          */
01398         if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
01399                 mutex_lock(&local->sta_mtx);
01400 
01401                 list_for_each_entry(sta, &local->sta_list, list) {
01402                         ieee80211_sta_tear_down_BA_sessions(sta, true);
01403                         clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
01404                 }
01405 
01406                 mutex_unlock(&local->sta_mtx);
01407         }
01408 
01409         ieee80211_wake_queues_by_reason(hw,
01410                         IEEE80211_QUEUE_STOP_REASON_SUSPEND);
01411 
01412         /*
01413          * If this is for hw restart things are still running.
01414          * We may want to change that later, however.
01415          */
01416         if (!local->suspended)
01417                 return 0;
01418 
01419 #ifdef CONFIG_PM
01420         /* first set suspended false, then resuming */
01421         local->suspended = false;
01422         mb();
01423         local->resuming = false;
01424 
01425         list_for_each_entry(sdata, &local->interfaces, list) {
01426                 switch(sdata->vif.type) {
01427                 case NL80211_IFTYPE_STATION:
01428                         ieee80211_sta_restart(sdata);
01429                         break;
01430                 case NL80211_IFTYPE_ADHOC:
01431                         ieee80211_ibss_restart(sdata);
01432                         break;
01433                 case NL80211_IFTYPE_MESH_POINT:
01434                         ieee80211_mesh_restart(sdata);
01435                         break;
01436                 default:
01437                         break;
01438                 }
01439         }
01440 
01441         mod_timer(&local->sta_cleanup, jiffies + 1);
01442 
01443         mutex_lock(&local->sta_mtx);
01444         list_for_each_entry(sta, &local->sta_list, list)
01445                 mesh_plink_restart(sta);
01446         mutex_unlock(&local->sta_mtx);
01447 #else
01448         WARN_ON(1);
01449 #endif
01450         return 0;
01451 }
01452 
01453 void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
01454 {
01455         struct ieee80211_sub_if_data *sdata;
01456         struct ieee80211_local *local;
01457         struct ieee80211_key *key;
01458 
01459         if (WARN_ON(!vif))
01460                 return;
01461 
01462         sdata = vif_to_sdata(vif);
01463         local = sdata->local;
01464 
01465         if (WARN_ON(!local->resuming))
01466                 return;
01467 
01468         if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
01469                 return;
01470 
01471         sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME;
01472 
01473         mutex_lock(&local->key_mtx);
01474         list_for_each_entry(key, &sdata->key_list, list)
01475                 key->flags |= KEY_FLAG_TAINTED;
01476         mutex_unlock(&local->key_mtx);
01477 }
01478 EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
01479 
01480 static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
01481                           enum ieee80211_smps_mode *smps_mode)
01482 {
01483         if (ifmgd->associated) {
01484                 *smps_mode = ifmgd->ap_smps;
01485 
01486                 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
01487                         if (ifmgd->powersave)
01488                                 *smps_mode = IEEE80211_SMPS_DYNAMIC;
01489                         else
01490                                 *smps_mode = IEEE80211_SMPS_OFF;
01491                 }
01492 
01493                 return 1;
01494         }
01495 
01496         return 0;
01497 }
01498 
01499 /* must hold iflist_mtx */
01500 void ieee80211_recalc_smps(struct ieee80211_local *local)
01501 {
01502         struct ieee80211_sub_if_data *sdata;
01503         enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
01504         int count = 0;
01505 
01506         lockdep_assert_held(&local->iflist_mtx);
01507 
01508         /*
01509          * This function could be improved to handle multiple
01510          * interfaces better, but right now it makes any
01511          * non-station interfaces force SM PS to be turned
01512          * off. If there are multiple station interfaces it
01513          * could also use the best possible mode, e.g. if
01514          * one is in static and the other in dynamic then
01515          * dynamic is ok.
01516          */
01517 
01518         list_for_each_entry(sdata, &local->interfaces, list) {
01519                 if (!ieee80211_sdata_running(sdata))
01520                         continue;
01521                 if (sdata->vif.type != NL80211_IFTYPE_STATION)
01522                         goto set;
01523 
01524                 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
01525 
01526                 if (count > 1) {
01527                         smps_mode = IEEE80211_SMPS_OFF;
01528                         break;
01529                 }
01530         }
01531 
01532         if (smps_mode == local->smps_mode)
01533                 return;
01534 
01535  set:
01536         local->smps_mode = smps_mode;
01537         /* changed flag is auto-detected for this */
01538         ieee80211_hw_config(local, 0);
01539 }
01540 
01541 static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
01542 {
01543         int i;
01544 
01545         for (i = 0; i < n_ids; i++)
01546                 if (ids[i] == id)
01547                         return true;
01548         return false;
01549 }
01550 
01576 size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
01577                           const u8 *ids, int n_ids, size_t offset)
01578 {
01579         size_t pos = offset;
01580 
01581         while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
01582                 pos += 2 + ies[pos + 1];
01583 
01584         return pos;
01585 }
01586 
01587 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
01588 {
01589         size_t pos = offset;
01590 
01591         while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC)
01592                 pos += 2 + ies[pos + 1];
01593 
01594         return pos;
01595 }
01596 
01597 static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
01598                                             int rssi_min_thold,
01599                                             int rssi_max_thold)
01600 {
01601         trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
01602 
01603         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
01604                 return;
01605 
01606         /*
01607          * Scale up threshold values before storing it, as the RSSI averaging
01608          * algorithm uses a scaled up value as well. Change this scaling
01609          * factor if the RSSI averaging algorithm changes.
01610          */
01611         sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
01612         sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
01613 }
01614 
01615 void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
01616                                     int rssi_min_thold,
01617                                     int rssi_max_thold)
01618 {
01619         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
01620 
01621         WARN_ON(rssi_min_thold == rssi_max_thold ||
01622                 rssi_min_thold > rssi_max_thold);
01623 
01624         _ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
01625                                        rssi_max_thold);
01626 }
01627 EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
01628 
01629 void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
01630 {
01631         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
01632 
01633         _ieee80211_enable_rssi_reports(sdata, 0, 0);
01634 }
01635 EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
01636 
01637 u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
01638                               u16 cap)
01639 {
01640         __le16 tmp;
01641 
01642         *pos++ = WLAN_EID_HT_CAPABILITY;
01643         *pos++ = sizeof(struct ieee80211_ht_cap);
01644         memset(pos, 0, sizeof(struct ieee80211_ht_cap));
01645 
01646         /* capability flags */
01647         tmp = cpu_to_le16(cap);
01648         memcpy(pos, &tmp, sizeof(u16));
01649         pos += sizeof(u16);
01650 
01651         /* AMPDU parameters */
01652         *pos++ = ht_cap->ampdu_factor |
01653                  (ht_cap->ampdu_density <<
01654                         IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
01655 
01656         /* MCS set */
01657         memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs));
01658         pos += sizeof(ht_cap->mcs);
01659 
01660         /* extended capabilities */
01661         pos += sizeof(__le16);
01662 
01663         /* BF capabilities */
01664         pos += sizeof(__le32);
01665 
01666         /* antenna selection */
01667         pos += sizeof(u8);
01668 
01669         return pos;
01670 }
01671 
01672 u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
01673                                struct ieee80211_channel *channel,
01674                                enum nl80211_channel_type channel_type,
01675                                u16 prot_mode)
01676 {
01677         struct ieee80211_ht_operation *ht_oper;
01678         /* Build HT Information */
01679         *pos++ = WLAN_EID_HT_OPERATION;
01680         *pos++ = sizeof(struct ieee80211_ht_operation);
01681         ht_oper = (struct ieee80211_ht_operation *)pos;
01682         ht_oper->primary_chan =
01683                         ieee80211_frequency_to_channel(channel->center_freq);
01684         switch (channel_type) {
01685         case NL80211_CHAN_HT40MINUS:
01686                 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
01687                 break;
01688         case NL80211_CHAN_HT40PLUS:
01689                 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
01690                 break;
01691         case NL80211_CHAN_HT20:
01692         default:
01693                 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
01694                 break;
01695         }
01696         if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
01697             channel_type != NL80211_CHAN_NO_HT &&
01698             channel_type != NL80211_CHAN_HT20)
01699                 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
01700 
01701         ht_oper->operation_mode = cpu_to_le16(prot_mode);
01702         ht_oper->stbc_param = 0x0000;
01703 
01704         /* It seems that Basic MCS set and Supported MCS set
01705            are identical for the first 10 bytes */
01706         memset(&ht_oper->basic_set, 0, 16);
01707         memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10);
01708 
01709         return pos + sizeof(struct ieee80211_ht_operation);
01710 }
01711 
01712 enum nl80211_channel_type
01713 ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper)
01714 {
01715         enum nl80211_channel_type channel_type;
01716 
01717         if (!ht_oper)
01718                 return NL80211_CHAN_NO_HT;
01719 
01720         switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
01721         case IEEE80211_HT_PARAM_CHA_SEC_NONE:
01722                 channel_type = NL80211_CHAN_HT20;
01723                 break;
01724         case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
01725                 channel_type = NL80211_CHAN_HT40PLUS;
01726                 break;
01727         case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
01728                 channel_type = NL80211_CHAN_HT40MINUS;
01729                 break;
01730         default:
01731                 channel_type = NL80211_CHAN_NO_HT;
01732         }
01733 
01734         return channel_type;
01735 }
01736 
01737 int ieee80211_add_srates_ie(struct ieee80211_vif *vif,
01738                             struct sk_buff *skb, bool need_basic)
01739 {
01740         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
01741         struct ieee80211_local *local = sdata->local;
01742         struct ieee80211_supported_band *sband;
01743         int rate;
01744         u8 i, rates, *pos;
01745         u32 basic_rates = vif->bss_conf.basic_rates;
01746 
01747         sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
01748         rates = sband->n_bitrates;
01749         if (rates > 8)
01750                 rates = 8;
01751 
01752         if (skb_tailroom(skb) < rates + 2)
01753                 return -ENOMEM;
01754 
01755         pos = skb_put(skb, rates + 2);
01756         *pos++ = WLAN_EID_SUPP_RATES;
01757         *pos++ = rates;
01758         for (i = 0; i < rates; i++) {
01759                 u8 basic = 0;
01760                 if (need_basic && basic_rates & BIT(i))
01761                         basic = 0x80;
01762                 rate = sband->bitrates[i].bitrate;
01763                 *pos++ = basic | (u8) (rate / 5);
01764         }
01765 
01766         return 0;
01767 }
01768 
01769 int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
01770                                 struct sk_buff *skb, bool need_basic)
01771 {
01772         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
01773         struct ieee80211_local *local = sdata->local;
01774         struct ieee80211_supported_band *sband;
01775         int rate;
01776         u8 i, exrates, *pos;
01777         u32 basic_rates = vif->bss_conf.basic_rates;
01778 
01779         sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
01780         exrates = sband->n_bitrates;
01781         if (exrates > 8)
01782                 exrates -= 8;
01783         else
01784                 exrates = 0;
01785 
01786         if (skb_tailroom(skb) < exrates + 2)
01787                 return -ENOMEM;
01788 
01789         if (exrates) {
01790                 pos = skb_put(skb, exrates + 2);
01791                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
01792                 *pos++ = exrates;
01793                 for (i = 8; i < sband->n_bitrates; i++) {
01794                         u8 basic = 0;
01795                         if (need_basic && basic_rates & BIT(i))
01796                                 basic = 0x80;
01797                         rate = sband->bitrates[i].bitrate;
01798                         *pos++ = basic | (u8) (rate / 5);
01799                 }
01800         }
01801         return 0;
01802 }
01803 
01804 int ieee80211_ave_rssi(struct ieee80211_vif *vif)
01805 {
01806         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
01807         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
01808 
01809         if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION)) {
01810                 /* non-managed type inferfaces */
01811                 return 0;
01812         }
01813         return ifmgd->ave_beacon_signal;
01814 }
01815 EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);


ros_rt_wmp
Author(s): Danilo Tardioli, dantard@unizar.es
autogenerated on Fri Jan 3 2014 12:07:56