]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/mac80211/util.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/ide-2.6
[karo-tx-linux.git] / net / mac80211 / util.c
index 0689a8fbd1e63f58aa829cadeb2dd9019c96c4f8..915e77769312ea85aace93ca1f20910ea9342a4c 100644 (file)
 /* privid for wiphys to determine whether they belong to us or not */
 void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
 
-/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
-/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
-const unsigned char rfc1042_header[] __aligned(2) =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
-
-/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
-const unsigned char bridge_tunnel_header[] __aligned(2) =
-       { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
-
 struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
 {
        struct ieee80211_local *local;
@@ -103,70 +94,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
        return NULL;
 }
 
-unsigned int ieee80211_hdrlen(__le16 fc)
-{
-       unsigned int hdrlen = 24;
-
-       if (ieee80211_is_data(fc)) {
-               if (ieee80211_has_a4(fc))
-                       hdrlen = 30;
-               if (ieee80211_is_data_qos(fc))
-                       hdrlen += IEEE80211_QOS_CTL_LEN;
-               goto out;
-       }
-
-       if (ieee80211_is_ctl(fc)) {
-               /*
-                * ACK and CTS are 10 bytes, all others 16. To see how
-                * to get this condition consider
-                *   subtype mask:   0b0000000011110000 (0x00F0)
-                *   ACK subtype:    0b0000000011010000 (0x00D0)
-                *   CTS subtype:    0b0000000011000000 (0x00C0)
-                *   bits that matter:         ^^^      (0x00E0)
-                *   value of those: 0b0000000011000000 (0x00C0)
-                */
-               if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
-                       hdrlen = 10;
-               else
-                       hdrlen = 16;
-       }
-out:
-       return hdrlen;
-}
-EXPORT_SYMBOL(ieee80211_hdrlen);
-
-unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
-{
-       const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data;
-       unsigned int hdrlen;
-
-       if (unlikely(skb->len < 10))
-               return 0;
-       hdrlen = ieee80211_hdrlen(hdr->frame_control);
-       if (unlikely(hdrlen > skb->len))
-               return 0;
-       return hdrlen;
-}
-EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
-
-int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
-{
-       int ae = meshhdr->flags & IEEE80211S_FLAGS_AE;
-       /* 7.1.3.5a.2 */
-       switch (ae) {
-       case 0:
-               return 6;
-       case 1:
-               return 12;
-       case 2:
-               return 18;
-       case 3:
-               return 24;
-       default:
-               return 6;
-       }
-}
-
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
 {
        struct sk_buff *skb = tx->skb;
@@ -414,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
 }
 EXPORT_SYMBOL(ieee80211_stop_queue);
 
+void ieee80211_add_pending_skb(struct ieee80211_local *local,
+                              struct sk_buff *skb)
+{
+       struct ieee80211_hw *hw = &local->hw;
+       unsigned long flags;
+       int queue = skb_get_queue_mapping(skb);
+
+       spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+       __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+       __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING);
+       skb_queue_tail(&local->pending[queue], skb);
+       __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+}
+
+int ieee80211_add_pending_skbs(struct ieee80211_local *local,
+                              struct sk_buff_head *skbs)
+{
+       struct ieee80211_hw *hw = &local->hw;
+       struct sk_buff *skb;
+       unsigned long flags;
+       int queue, ret = 0, i;
+
+       spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
+       for (i = 0; i < hw->queues; i++)
+               __ieee80211_stop_queue(hw, i,
+                       IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+
+       while ((skb = skb_dequeue(skbs))) {
+               ret++;
+               queue = skb_get_queue_mapping(skb);
+               skb_queue_tail(&local->pending[queue], skb);
+       }
+
+       for (i = 0; i < hw->queues; i++) {
+               if (ret)
+                       __ieee80211_stop_queue(hw, i,
+                               IEEE80211_QUEUE_STOP_REASON_PENDING);
+               __ieee80211_wake_queue(hw, i,
+                       IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
+       }
+       spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
+
+       return ret;
+}
+
 void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
                                    enum queue_stop_reason reason)
 {
@@ -730,15 +703,15 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
 
                switch (queue) {
                case 3: /* AC_BK */
-                       qparam.cw_max = aCWmin;
-                       qparam.cw_min = aCWmax;
+                       qparam.cw_max = aCWmax;
+                       qparam.cw_min = aCWmin;
                        qparam.txop = 0;
                        qparam.aifs = 7;
                        break;
                default: /* never happens but let's not leave undefined */
                case 2: /* AC_BE */
-                       qparam.cw_max = aCWmin;
-                       qparam.cw_min = aCWmax;
+                       qparam.cw_max = aCWmax;
+                       qparam.cw_min = aCWmin;
                        qparam.txop = 0;
                        qparam.aifs = 3;
                        break;
@@ -801,31 +774,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
        dev_queue_xmit(skb);
 }
 
-int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
-{
-       int ret = -EINVAL;
-       struct ieee80211_channel *chan;
-       struct ieee80211_local *local = sdata->local;
-
-       chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
-
-       if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
-               if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
-                   chan->flags & IEEE80211_CHAN_NO_IBSS)
-                       return ret;
-               local->oper_channel = chan;
-               local->oper_channel_type = NL80211_CHAN_NO_HT;
-
-               if (local->sw_scanning || local->hw_scanning)
-                       ret = 0;
-               else
-                       ret = ieee80211_hw_config(
-                               local, IEEE80211_CONF_CHANGE_CHANNEL);
-       }
-
-       return ret;
-}
-
 u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
                              enum ieee80211_band band)
 {
@@ -1034,12 +982,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        struct sta_info *sta;
        unsigned long flags;
        int res;
+       bool from_suspend = local->suspended;
+
+       /*
+        * We're going to start the hardware, at that point
+        * we are no longer suspended and can RX frames.
+        */
+       local->suspended = false;
 
        /* restart hardware */
        if (local->open_count) {
                res = drv_start(local);
 
-               ieee80211_led_radio(local, hw->conf.radio_enabled);
+               ieee80211_led_radio(local, true);
        }
 
        /* add interfaces */
@@ -1058,6 +1013,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        if (local->ops->sta_notify) {
                spin_lock_irqsave(&local->sta_lock, flags);
                list_for_each_entry(sta, &local->sta_list, list) {
+                       sdata = sta->sdata;
                        if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                                sdata = container_of(sdata->bss,
                                             struct ieee80211_sub_if_data,
@@ -1128,5 +1084,40 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        ieee80211_wake_queues_by_reason(hw,
                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
+       /*
+        * If this is for hw restart things are still running.
+        * We may want to change that later, however.
+        */
+       if (!from_suspend)
+               return 0;
+
+#ifdef CONFIG_PM
+       local->suspended = false;
+
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               switch(sdata->vif.type) {
+               case NL80211_IFTYPE_STATION:
+                       ieee80211_sta_restart(sdata);
+                       break;
+               case NL80211_IFTYPE_ADHOC:
+                       ieee80211_ibss_restart(sdata);
+                       break;
+               case NL80211_IFTYPE_MESH_POINT:
+                       ieee80211_mesh_restart(sdata);
+                       break;
+               default:
+                       break;
+               }
+       }
+
+       add_timer(&local->sta_cleanup);
+
+       spin_lock_irqsave(&local->sta_lock, flags);
+       list_for_each_entry(sta, &local->sta_list, list)
+               mesh_plink_restart(sta);
+       spin_unlock_irqrestore(&local->sta_lock, flags);
+#else
+       WARN_ON(1);
+#endif
        return 0;
 }