]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
authorDavid S. Miller <davem@davemloft.net>
Tue, 15 Jul 2008 03:40:34 +0000 (20:40 -0700)
committerDavid S. Miller <davem@davemloft.net>
Tue, 15 Jul 2008 03:40:34 +0000 (20:40 -0700)
62 files changed:
Documentation/feature-removal-schedule.txt
drivers/net/wireless/ath5k/base.c
drivers/net/wireless/b43/main.c
drivers/net/wireless/b43/xmit.c
drivers/net/wireless/b43legacy/main.c
drivers/net/wireless/b43legacy/xmit.c
drivers/net/wireless/iwlwifi/iwl-3945-led.c
drivers/net/wireless/iwlwifi/iwl-3945-led.h
drivers/net/wireless/iwlwifi/iwl-3945.c
drivers/net/wireless/iwlwifi/iwl-3945.h
drivers/net/wireless/iwlwifi/iwl-4965-hw.h
drivers/net/wireless/iwlwifi/iwl-4965-rs.c
drivers/net/wireless/iwlwifi/iwl-4965.c
drivers/net/wireless/iwlwifi/iwl-5000-hw.h
drivers/net/wireless/iwlwifi/iwl-5000.c
drivers/net/wireless/iwlwifi/iwl-commands.h
drivers/net/wireless/iwlwifi/iwl-core.c
drivers/net/wireless/iwlwifi/iwl-core.h
drivers/net/wireless/iwlwifi/iwl-dev.h
drivers/net/wireless/iwlwifi/iwl-led.c
drivers/net/wireless/iwlwifi/iwl-led.h
drivers/net/wireless/iwlwifi/iwl-rx.c
drivers/net/wireless/iwlwifi/iwl-scan.c
drivers/net/wireless/iwlwifi/iwl-tx.c
drivers/net/wireless/iwlwifi/iwl3945-base.c
drivers/net/wireless/iwlwifi/iwl4965-base.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2x00.h
drivers/net/wireless/rt2x00/rt2x00config.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt2x00firmware.c
drivers/net/wireless/rt2x00/rt2x00lib.h
drivers/net/wireless/rt2x00/rt2x00mac.c
drivers/net/wireless/rt2x00/rt2x00queue.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rtl8187_dev.c
drivers/net/wireless/rtl8187_rtl8225.c
drivers/net/wireless/rtl8187_rtl8225.h
drivers/net/wireless/zd1211rw/zd_mac.c
include/linux/ssb/ssb.h
include/net/mac80211.h
net/core/net-sysfs.c
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/debugfs_netdev.c
net/mac80211/debugfs_netdev.h
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/main.c
net/mac80211/mlme.c
net/mac80211/rc80211_pid_algo.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/sta_info.h
net/mac80211/tx.c
net/mac80211/util.c
net/mac80211/wext.c
net/wireless/Kconfig

index 8319c462c9f03d74625583f59b74fe11889e0a6a..db300e09c9ac5f98dde04c74f63e5eb2bead0b64 100644 (file)
@@ -333,3 +333,13 @@ Why:       This option was introduced just to allow older lm-sensors userspace
        to keep working over the upgrade to 2.6.26. At the scheduled time of
        removal fixed lm-sensors (2.x or 3.x) should be readily available.
 Who:   Rene Herman <rene.herman@gmail.com>
+
+---------------------------
+
+What:  Code that is now under CONFIG_WIRELESS_EXT_SYSFS
+       (in net/core/net-sysfs.c)
+When:  After the only user (hal) has seen a release with the patches
+       for enough time, probably some time in 2010.
+Why:   Over 1K .text/.data size reduction, data is available in other
+       ways (ioctls)
+Who:   Johannes Berg <johannes@sipsolutions.net>
index a43e9b25169b1e78e5b05662202a015a15d7174d..217d506527a96d2f72e887f75b9cab2425554e0f 100644 (file)
@@ -207,7 +207,6 @@ static struct ieee80211_ops ath5k_hw_ops = {
        .get_tx_stats   = ath5k_get_tx_stats,
        .get_tsf        = ath5k_get_tsf,
        .reset_tsf      = ath5k_reset_tsf,
-       .beacon_update  = ath5k_beacon_update,
 };
 
 /*
@@ -2785,6 +2784,18 @@ ath5k_config_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
                 * a clean way of letting us retrieve this yet. */
                ath5k_hw_set_associd(ah, ah->ah_bssid, 0);
        }
+
+       if (conf->changed & IEEE80211_IFCC_BEACON &&
+           vif->type == IEEE80211_IF_TYPE_IBSS) {
+               struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+               if (!beacon) {
+                       ret = -ENOMEM;
+                       goto unlock;
+               }
+               /* call old handler for now */
+               ath5k_beacon_update(hw, beacon);
+       }
+
        mutex_unlock(&sc->lock);
 
        return ath5k_reset(hw);
index 9d2eb273b726da910293bc9cac0ff811169a32a5..381dbd33dfc2cecbd2cefb5d78ffa445f6b5e788 100644 (file)
@@ -1675,14 +1675,24 @@ static void b43_beacon_update_trigger_work(struct work_struct *work)
 
 /* Asynchronously update the packet templates in template RAM.
  * Locking: Requires wl->irq_lock to be locked. */
-static void b43_update_templates(struct b43_wl *wl, struct sk_buff *beacon)
+static void b43_update_templates(struct b43_wl *wl)
 {
+       struct sk_buff *beacon;
+
        /* This is the top half of the ansynchronous beacon update.
         * The bottom half is the beacon IRQ.
         * Beacon update must be asynchronous to avoid sending an
         * invalid beacon. This can happen for example, if the firmware
         * transmits a beacon while we are updating it. */
 
+       /* We could modify the existing beacon and set the aid bit in
+        * the TIM field, but that would probably require resizing and
+        * moving of data within the beacon template.
+        * Simply request a new beacon and let mac80211 do the hard work. */
+       beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+       if (unlikely(!beacon))
+               return;
+
        if (wl->current_beacon)
                dev_kfree_skb_any(wl->current_beacon);
        wl->current_beacon = beacon;
@@ -3645,10 +3655,14 @@ static int b43_op_config_interface(struct ieee80211_hw *hw,
        if (b43_status(dev) >= B43_STAT_INITIALIZED) {
                if (b43_is_mode(wl, IEEE80211_IF_TYPE_AP) ||
                    b43_is_mode(wl, IEEE80211_IF_TYPE_MESH_POINT)) {
-                       B43_WARN_ON(conf->type != wl->if_type);
-                       b43_set_ssid(dev, conf->ssid, conf->ssid_len);
-                       if (conf->beacon)
-                               b43_update_templates(wl, conf->beacon);
+                       B43_WARN_ON(vif->type != wl->if_type);
+                       if (conf->changed & IEEE80211_IFCC_SSID)
+                               b43_set_ssid(dev, conf->ssid, conf->ssid_len);
+                       if (conf->changed & IEEE80211_IFCC_BEACON)
+                               b43_update_templates(wl);
+               } else if (b43_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
+                       if (conf->changed & IEEE80211_IFCC_BEACON)
+                               b43_update_templates(wl);
                }
                b43_write_mac_bssid_templates(dev);
        }
@@ -4334,33 +4348,12 @@ out_unlock:
 }
 
 static int b43_op_beacon_set_tim(struct ieee80211_hw *hw, int aid, int set)
-{
-       struct b43_wl *wl = hw_to_b43_wl(hw);
-       struct sk_buff *beacon;
-       unsigned long flags;
-
-       /* We could modify the existing beacon and set the aid bit in
-        * the TIM field, but that would probably require resizing and
-        * moving of data within the beacon template.
-        * Simply request a new beacon and let mac80211 do the hard work. */
-       beacon = ieee80211_beacon_get(hw, wl->vif);
-       if (unlikely(!beacon))
-               return -ENOMEM;
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       b43_update_templates(wl, beacon);
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-
-       return 0;
-}
-
-static int b43_op_ibss_beacon_update(struct ieee80211_hw *hw,
-                                    struct sk_buff *beacon)
 {
        struct b43_wl *wl = hw_to_b43_wl(hw);
        unsigned long flags;
 
        spin_lock_irqsave(&wl->irq_lock, flags);
-       b43_update_templates(wl, beacon);
+       b43_update_templates(wl);
        spin_unlock_irqrestore(&wl->irq_lock, flags);
 
        return 0;
@@ -4391,7 +4384,6 @@ static const struct ieee80211_ops b43_hw_ops = {
        .stop                   = b43_op_stop,
        .set_retry_limit        = b43_op_set_retry_limit,
        .set_tim                = b43_op_beacon_set_tim,
-       .beacon_update          = b43_op_ibss_beacon_update,
        .sta_notify             = b43_op_sta_notify,
 };
 
index bf6f6c1ed4cf5193117a88da50493a3e965b6426..8d54502222a6ed78534b8681f5f7fcbe1f12064b 100644 (file)
@@ -317,7 +317,8 @@ int b43_generate_txhdr(struct b43_wldev *dev,
        /* MAC control */
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
                mac_ctl |= B43_TXH_MAC_ACK;
-       if (!ieee80211_is_pspoll(fctl))
+       /* use hardware sequence counter as the non-TID counter */
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
                mac_ctl |= B43_TXH_MAC_HWSEQ;
        if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                mac_ctl |= B43_TXH_MAC_STMSDU;
index 069157eea05cfd44f346326e587e569dee5fe720..a1b8bf3ee73245ebe1d9802581f4537827a4624f 100644 (file)
@@ -1138,14 +1138,22 @@ static void b43legacy_write_probe_resp_template(struct b43legacy_wldev *dev,
 
 /* Asynchronously update the packet templates in template RAM.
  * Locking: Requires wl->irq_lock to be locked. */
-static void b43legacy_update_templates(struct b43legacy_wl *wl,
-                                      struct sk_buff *beacon)
+static void b43legacy_update_templates(struct b43legacy_wl *wl)
 {
+       struct sk_buff *beacon;
        /* This is the top half of the ansynchronous beacon update. The bottom
         * half is the beacon IRQ. Beacon update must be asynchronous to avoid
         * sending an invalid beacon. This can happen for example, if the
         * firmware transmits a beacon while we are updating it. */
 
+       /* We could modify the existing beacon and set the aid bit in the TIM
+        * field, but that would probably require resizing and moving of data
+        * within the beacon template. Simply request a new beacon and let
+        * mac80211 do the hard work. */
+       beacon = ieee80211_beacon_get(wl->hw, wl->vif);
+       if (unlikely(!beacon))
+               return;
+
        if (wl->current_beacon)
                dev_kfree_skb_any(wl->current_beacon);
        wl->current_beacon = beacon;
@@ -2727,10 +2735,13 @@ static int b43legacy_op_config_interface(struct ieee80211_hw *hw,
                memset(wl->bssid, 0, ETH_ALEN);
        if (b43legacy_status(dev) >= B43legacy_STAT_INITIALIZED) {
                if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_AP)) {
-                       B43legacy_WARN_ON(conf->type != IEEE80211_IF_TYPE_AP);
+                       B43legacy_WARN_ON(vif->type != IEEE80211_IF_TYPE_AP);
                        b43legacy_set_ssid(dev, conf->ssid, conf->ssid_len);
-                       if (conf->beacon)
-                               b43legacy_update_templates(wl, conf->beacon);
+                       if (conf->changed & IEEE80211_IFCC_BEACON)
+                               b43legacy_update_templates(wl);
+               } else if (b43legacy_is_mode(wl, IEEE80211_IF_TYPE_IBSS)) {
+                       if (conf->changed & IEEE80211_IFCC_BEACON)
+                               b43legacy_update_templates(wl);
                }
                b43legacy_write_mac_bssid_templates(dev);
        }
@@ -3394,33 +3405,12 @@ out_unlock:
 
 static int b43legacy_op_beacon_set_tim(struct ieee80211_hw *hw,
                                       int aid, int set)
-{
-       struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
-       struct sk_buff *beacon;
-       unsigned long flags;
-
-       /* We could modify the existing beacon and set the aid bit in the TIM
-        * field, but that would probably require resizing and moving of data
-        * within the beacon template. Simply request a new beacon and let
-        * mac80211 do the hard work. */
-       beacon = ieee80211_beacon_get(hw, wl->vif);
-       if (unlikely(!beacon))
-               return -ENOMEM;
-       spin_lock_irqsave(&wl->irq_lock, flags);
-       b43legacy_update_templates(wl, beacon);
-       spin_unlock_irqrestore(&wl->irq_lock, flags);
-
-       return 0;
-}
-
-static int b43legacy_op_ibss_beacon_update(struct ieee80211_hw *hw,
-                                          struct sk_buff *beacon)
 {
        struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
        unsigned long flags;
 
        spin_lock_irqsave(&wl->irq_lock, flags);
-       b43legacy_update_templates(wl, beacon);
+       b43legacy_update_templates(wl);
        spin_unlock_irqrestore(&wl->irq_lock, flags);
 
        return 0;
@@ -3440,7 +3430,6 @@ static const struct ieee80211_ops b43legacy_hw_ops = {
        .stop                   = b43legacy_op_stop,
        .set_retry_limit        = b43legacy_op_set_retry_limit,
        .set_tim                = b43legacy_op_beacon_set_tim,
-       .beacon_update          = b43legacy_op_ibss_beacon_update,
 };
 
 /* Hard-reset the chip. Do not call this directly.
index a3540787eb507bfe4809d58008dae28c738c6666..e969ed8d412dd6d42638e12521dac9a7a57b5600 100644 (file)
@@ -295,8 +295,7 @@ static int generate_txhdr_fw3(struct b43legacy_wldev *dev,
        /* MAC control */
        if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
                mac_ctl |= B43legacy_TX4_MAC_ACK;
-       if (!(((fctl & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_CTL) &&
-             ((fctl & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_PSPOLL)))
+       if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)
                mac_ctl |= B43legacy_TX4_MAC_HWSEQ;
        if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
                mac_ctl |= B43legacy_TX4_MAC_STMSDU;
index 8b1528e52d43ad12dc8948249bb52d9894292a74..6be1fe13fa5751bad0217fa2bae2fa54fea96d8a 100644 (file)
 #include "iwl-3945.h"
 #include "iwl-helpers.h"
 
-#define IWL_1MB_RATE (128 * 1024)
-#define IWL_LED_THRESHOLD (16)
-#define IWL_MAX_BLINK_TBL (10)
 
 static const struct {
        u16 brightness;
        u8 on_time;
-       u8 of_time;
+       u8 off_time;
 } blink_tbl[] =
 {
        {300, 25, 25},
@@ -61,9 +58,16 @@ static const struct {
        {15, 95, 95 },
        {10, 110, 110},
        {5, 130, 130},
-       {0, 167, 167}
+       {0, 167, 167},
+       /*SOLID_ON*/
+       {-1, IWL_LED_SOLID, 0}
 };
 
+#define IWL_1MB_RATE (128 * 1024)
+#define IWL_LED_THRESHOLD (16)
+#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /*Exclude Solid on*/
+#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
+
 static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
                                    struct iwl3945_cmd *cmd,
                                    struct sk_buff *skb)
@@ -71,6 +75,10 @@ static int iwl3945_led_cmd_callback(struct iwl3945_priv *priv,
        return 1;
 }
 
+static inline int iwl3945_brightness_to_idx(enum led_brightness brightness)
+{
+       return fls(0x000000FF & (u32)brightness);
+}
 
 /* Send led command */
 static int iwl_send_led_cmd(struct iwl3945_priv *priv,
@@ -81,49 +89,45 @@ static int iwl_send_led_cmd(struct iwl3945_priv *priv,
                .len = sizeof(struct iwl3945_led_cmd),
                .data = led_cmd,
                .meta.flags = CMD_ASYNC,
-               .meta.u.callback = iwl3945_led_cmd_callback
+               .meta.u.callback = iwl3945_led_cmd_callback,
        };
 
        return iwl3945_send_cmd(priv, &cmd);
 }
 
 
+
 /* Set led on command */
-static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
+static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
+                              unsigned int idx)
 {
        struct iwl3945_led_cmd led_cmd = {
                .id = led_id,
-               .on = IWL_LED_SOLID,
-               .off = 0,
                .interval = IWL_DEF_LED_INTRVL
        };
+
+       BUG_ON(idx > IWL_MAX_BLINK_TBL);
+
+       led_cmd.on = blink_tbl[idx].on_time;
+       led_cmd.off = blink_tbl[idx].off_time;
+
        return iwl_send_led_cmd(priv, &led_cmd);
 }
 
+
+#if 1
 /* Set led on command */
-static int iwl3945_led_pattern(struct iwl3945_priv *priv, int led_id,
-                              enum led_brightness brightness)
+static int iwl3945_led_on(struct iwl3945_priv *priv, int led_id)
 {
        struct iwl3945_led_cmd led_cmd = {
                .id = led_id,
-               .on = brightness,
-               .off = brightness,
+               .on = IWL_LED_SOLID,
+               .off = 0,
                .interval = IWL_DEF_LED_INTRVL
        };
-       if (brightness == LED_FULL) {
-               led_cmd.on = IWL_LED_SOLID;
-               led_cmd.off = 0;
-       }
        return iwl_send_led_cmd(priv, &led_cmd);
 }
 
-/* Set led register off */
-static int iwl3945_led_on_reg(struct iwl3945_priv *priv, int led_id)
-{
-       IWL_DEBUG_LED("led on %d\n", led_id);
-       return iwl3945_led_on(priv, led_id);
-}
-
 /* Set led off command */
 static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
 {
@@ -136,27 +140,7 @@ static int iwl3945_led_off(struct iwl3945_priv *priv, int led_id)
        IWL_DEBUG_LED("led off %d\n", led_id);
        return iwl_send_led_cmd(priv, &led_cmd);
 }
-
-/* Set led register off */
-static int iwl3945_led_off_reg(struct iwl3945_priv *priv, int led_id)
-{
-       iwl3945_led_off(priv, led_id);
-       return 0;
-}
-
-/* Set led blink command */
-static int iwl3945_led_not_solid(struct iwl3945_priv *priv, int led_id,
-                              u8 brightness)
-{
-       struct iwl3945_led_cmd led_cmd = {
-               .id = led_id,
-               .on = brightness,
-               .off = brightness,
-               .interval = IWL_DEF_LED_INTRVL
-       };
-
-       return iwl_send_led_cmd(priv, &led_cmd);
-}
+#endif
 
 
 /*
@@ -206,8 +190,10 @@ static void iwl3945_led_brightness_set(struct led_classdev *led_cdev,
                        led->led_off(priv, IWL_LED_LINK);
                break;
        default:
-               if (led->led_pattern)
-                       led->led_pattern(priv, IWL_LED_LINK, brightness);
+               if (led->led_pattern) {
+                       int idx = iwl3945_brightness_to_idx(brightness);
+                       led->led_pattern(priv, IWL_LED_LINK, idx);
+               }
                break;
        }
 }
@@ -252,24 +238,20 @@ static int iwl3945_led_register_led(struct iwl3945_priv *priv,
 static inline u8 get_blink_rate(struct iwl3945_priv *priv)
 {
        int index;
-       u8 blink_rate;
-
-       if (priv->rxtxpackets < IWL_LED_THRESHOLD)
-               index = 10;
-       else {
-               for (index = 0; index < IWL_MAX_BLINK_TBL; index++) {
-                       if (priv->rxtxpackets > (blink_tbl[index].brightness *
-                                                IWL_1MB_RATE))
-                               break;
-               }
-       }
-       /* if 0 frame is transfered */
-       if ((index == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
-               blink_rate = IWL_LED_SOLID;
-       else
-               blink_rate = blink_tbl[index].on_time;
+       u64 current_tpt = priv->rxtxpackets;
+       s64 tpt = current_tpt - priv->led_tpt;
 
-       return blink_rate;
+       if (tpt < 0)
+               tpt = -tpt;
+       priv->led_tpt = current_tpt;
+
+       if (!priv->allow_blinking)
+               index = IWL_MAX_BLINK_TBL;
+       else
+               for (index = 0; index < IWL_MAX_BLINK_TBL; index++)
+                       if (tpt > (blink_tbl[index].brightness * IWL_1MB_RATE))
+                               break;
+       return index;
 }
 
 static inline int is_rf_kill(struct iwl3945_priv *priv)
@@ -285,7 +267,7 @@ static inline int is_rf_kill(struct iwl3945_priv *priv)
  */
 void iwl3945_led_background(struct iwl3945_priv *priv)
 {
-       u8 blink_rate;
+       u8 blink_idx;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
                priv->last_blink_time = 0;
@@ -298,9 +280,10 @@ void iwl3945_led_background(struct iwl3945_priv *priv)
 
        if (!priv->allow_blinking) {
                priv->last_blink_time = 0;
-               if (priv->last_blink_rate != IWL_LED_SOLID) {
-                       priv->last_blink_rate = IWL_LED_SOLID;
-                       iwl3945_led_on(priv, IWL_LED_LINK);
+               if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
+                       priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
+                       iwl3945_led_pattern(priv, IWL_LED_LINK,
+                                           IWL_SOLID_BLINK_IDX);
                }
                return;
        }
@@ -309,21 +292,14 @@ void iwl3945_led_background(struct iwl3945_priv *priv)
                        msecs_to_jiffies(1000)))
                return;
 
-       blink_rate = get_blink_rate(priv);
+       blink_idx = get_blink_rate(priv);
 
        /* call only if blink rate change */
-       if (blink_rate != priv->last_blink_rate) {
-               if (blink_rate != IWL_LED_SOLID) {
-                       priv->last_blink_time = jiffies +
-                                               msecs_to_jiffies(1000);
-                       iwl3945_led_not_solid(priv, IWL_LED_LINK, blink_rate);
-               } else {
-                       priv->last_blink_time = 0;
-                       iwl3945_led_on(priv, IWL_LED_LINK);
-               }
-       }
+       if (blink_idx != priv->last_blink_rate)
+               iwl3945_led_pattern(priv, IWL_LED_LINK, blink_idx);
 
-       priv->last_blink_rate = blink_rate;
+       priv->last_blink_time = jiffies;
+       priv->last_blink_rate = blink_idx;
        priv->rxtxpackets = 0;
 }
 
@@ -337,6 +313,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
 
        priv->last_blink_rate = 0;
        priv->rxtxpackets = 0;
+       priv->led_tpt = 0;
        priv->last_blink_time = 0;
        priv->allow_blinking = 0;
 
@@ -344,8 +321,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
        snprintf(name, sizeof(name), "iwl-%s:radio",
                 wiphy_name(priv->hw->wiphy));
 
-       priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on_reg;
-       priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off_reg;
+       priv->led[IWL_LED_TRG_RADIO].led_on = iwl3945_led_on;
+       priv->led[IWL_LED_TRG_RADIO].led_off = iwl3945_led_off;
        priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
 
        ret = iwl3945_led_register_led(priv,
@@ -364,8 +341,8 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
                                   IWL_LED_TRG_ASSOC, 0,
                                   name, trigger);
        /* for assoc always turn led on */
-       priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on_reg;
-       priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on_reg;
+       priv->led[IWL_LED_TRG_ASSOC].led_on = iwl3945_led_on;
+       priv->led[IWL_LED_TRG_ASSOC].led_off = iwl3945_led_on;
        priv->led[IWL_LED_TRG_ASSOC].led_pattern = NULL;
 
        if (ret)
@@ -391,6 +368,7 @@ int iwl3945_led_register(struct iwl3945_priv *priv)
        trigger = ieee80211_get_tx_led_name(priv->hw);
        snprintf(name, sizeof(name), "iwl-%s:TX",
                 wiphy_name(priv->hw->wiphy));
+
        ret = iwl3945_led_register_led(priv,
                                   &priv->led[IWL_LED_TRG_TX],
                                   IWL_LED_TRG_TX, 0,
index b1d2f6b8b2599fe00dbccc281d05772783b01caf..47b7e0bac802e803170a333b557807047ffd30c6 100644 (file)
@@ -54,7 +54,7 @@ struct iwl3945_led {
        int (*led_on) (struct iwl3945_priv *priv, int led_id);
        int (*led_off) (struct iwl3945_priv *priv, int led_id);
        int (*led_pattern) (struct iwl3945_priv *priv, int led_id,
-                           enum led_brightness brightness);
+                           unsigned int idx);
 
        enum led_type type;
        unsigned int registered;
index 94e177a9f51ca0d3e39b4dd44b3caf8440e525ef..c2a76785b665b36730e5233d3bec655ca8c6127a 100644 (file)
@@ -514,6 +514,23 @@ static inline void iwl3945_dbg_report_frame(struct iwl3945_priv *priv,
 }
 #endif
 
+/* This is necessary only for a number of statistics, see the caller. */
+static int iwl3945_is_network_packet(struct iwl3945_priv *priv,
+               struct ieee80211_hdr *header)
+{
+       /* Filter incoming packets to determine if they are targeted toward
+        * this network, discarding packets coming from ourselves */
+       switch (priv->iw_mode) {
+       case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
+               /* packets to our IBSS update information */
+               return !compare_ether_addr(header->addr3, priv->bssid);
+       case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
+               /* packets to our IBSS update information */
+               return !compare_ether_addr(header->addr2, priv->bssid);
+       default:
+               return 1;
+       }
+}
 
 static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
                                 struct sk_buff *skb,
@@ -608,12 +625,12 @@ static void iwl3945_add_radiotap(struct iwl3945_priv *priv,
        stats->flag |= RX_FLAG_RADIOTAP;
 }
 
-static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
+static void iwl3945_pass_packet_to_mac80211(struct iwl3945_priv *priv,
                                   struct iwl3945_rx_mem_buffer *rxb,
                                   struct ieee80211_rx_status *stats)
 {
-       struct ieee80211_hdr *hdr;
        struct iwl3945_rx_packet *pkt = (struct iwl3945_rx_packet *)rxb->skb->data;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
        struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
        struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
        short len = le16_to_cpu(rx_hdr->len);
@@ -635,8 +652,6 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
        /* Set the size of the skb to the size of the frame */
        skb_put(rxb->skb, le16_to_cpu(rx_hdr->len));
 
-       hdr = (void *)rxb->skb->data;
-
        if (iwl3945_param_hwcrypto)
                iwl3945_set_decrypted_flag(priv, rxb->skb,
                                       le32_to_cpu(rx_end->status), stats);
@@ -645,7 +660,7 @@ static void iwl3945_handle_data_packet(struct iwl3945_priv *priv, int is_data,
                iwl3945_add_radiotap(priv, rxb->skb, rx_hdr, stats);
 
 #ifdef CONFIG_IWL3945_LEDS
-       if (is_data)
+       if (ieee80211_is_data(hdr->frame_control))
                priv->rxtxpackets += len;
 #endif
        ieee80211_rx_irqsafe(priv->hw, rxb->skb, stats);
@@ -694,7 +709,7 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
        }
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_MNTR) {
-               iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
+               iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
                return;
        }
 
@@ -842,27 +857,12 @@ static void iwl3945_rx_reply_rx(struct iwl3945_priv *priv,
                        }
                }
 
-               iwl3945_handle_data_packet(priv, 0, rxb, &rx_status);
-               break;
-
-       case IEEE80211_FTYPE_CTL:
-               break;
-
-       case IEEE80211_FTYPE_DATA: {
-               DECLARE_MAC_BUF(mac1);
-               DECLARE_MAC_BUF(mac2);
-               DECLARE_MAC_BUF(mac3);
-
-               if (unlikely(iwl3945_is_duplicate_packet(priv, header)))
-                       IWL_DEBUG_DROP("Dropping (dup): %s, %s, %s\n",
-                                      print_mac(mac1, header->addr1),
-                                      print_mac(mac2, header->addr2),
-                                      print_mac(mac3, header->addr3));
-               else
-                       iwl3945_handle_data_packet(priv, 1, rxb, &rx_status);
+       case IEEE80211_FTYPE_DATA:
+               /* fall through */
+       default:
+               iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
                break;
        }
-       }
 }
 
 int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl3945_priv *priv, void *ptr,
index 9c0a09eaca6f8f1bbd85a064a23e283bd4e73e47..fa81ba1af3d3266cdff3f63bb9bb91e6f0b20d1e 100644 (file)
@@ -510,8 +510,6 @@ struct iwl3945_ucode {
        u8 data[0];             /* data in same order as "size" elements */
 };
 
-#define IWL_IBSS_MAC_HASH_SIZE 32
-
 struct iwl3945_ibss_seq {
        u8 mac[ETH_ALEN];
        u16 seq_num;
@@ -569,17 +567,8 @@ extern int iwl3945_send_add_station(struct iwl3945_priv *priv,
                                struct iwl3945_addsta_cmd *sta, u8 flags);
 extern u8 iwl3945_add_station(struct iwl3945_priv *priv, const u8 *bssid,
                          int is_ap, u8 flags);
-extern int iwl3945_is_network_packet(struct iwl3945_priv *priv,
-                                struct ieee80211_hdr *header);
 extern int iwl3945_power_init_handle(struct iwl3945_priv *priv);
 extern int iwl3945_eeprom_init(struct iwl3945_priv *priv);
-extern void iwl3945_handle_data_packet_monitor(struct iwl3945_priv *priv,
-                                          struct iwl3945_rx_mem_buffer *rxb,
-                                          void *data, short len,
-                                          struct ieee80211_rx_status *stats,
-                                          u16 phy_flags);
-extern int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv,
-                                      struct ieee80211_hdr *header);
 extern int iwl3945_rx_queue_alloc(struct iwl3945_priv *priv);
 extern void iwl3945_rx_queue_reset(struct iwl3945_priv *priv,
                               struct iwl3945_rx_queue *rxq);
@@ -805,6 +794,7 @@ struct iwl3945_priv {
        u8 last_blink_rate;
        u8 allow_blinking;
        unsigned int rxtxpackets;
+       u64 led_tpt;
 #endif
 
 
@@ -859,14 +849,6 @@ struct iwl3945_priv {
        u32 last_beacon_time;
        u64 last_tsf;
 
-       /* Duplicate packet detection */
-       u16 last_seq_num;
-       u16 last_frag_num;
-       unsigned long last_packet_time;
-
-       /* Hash table for finding stations in IBSS network */
-       struct list_head ibss_mac_hash[IWL_IBSS_MAC_HASH_SIZE];
-
        /* eeprom */
        struct iwl3945_eeprom eeprom;
 
index 10f630e1afa633274fd0967dee7fd856aa59194d..fce950f4163c16327321118fb13fff7a6e86ad9a 100644 (file)
@@ -819,6 +819,7 @@ enum {
 #define IWL49_NUM_FIFOS        7
 #define IWL49_CMD_FIFO_NUM     4
 #define IWL49_NUM_QUEUES       16
+#define IWL49_NUM_AMPDU_QUEUES 8
 
 /**
  * struct iwl_tfd_frame_data
index c7ebb3bf06f5fd50cdc9e8415583e01cbb78f6f7..3ccb84aa5dbc0bf364e5f810d9d80d76669e45c1 100644 (file)
@@ -2265,9 +2265,7 @@ static void rs_rate_init(void *priv_rate, void *priv_sta,
 
        /* as default allow aggregation for all tids */
        lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
-#ifdef CONFIG_MAC80211_DEBUGFS
        lq_sta->drv = priv;
-#endif
 
        rs_initialize_lq(priv, conf, sta);
 }
index 04365b39279cff5b7adffcc5cb05a03c92335818..9afecb813716d90817bf180bef80008253dcf7d9 100644 (file)
 static int iwl4965_send_tx_power(struct iwl_priv *priv);
 static int iwl4965_hw_get_temperature(const struct iwl_priv *priv);
 
+/* Change firmware file name, using "-" and incrementing number,
+ *   *only* when uCode interface or architecture changes so that it
+ *   is not compatible with earlier drivers.
+ * This number will also appear in << 8 position of 1st dword of uCode file */
+#define IWL4965_UCODE_API "-2"
+
+
 /* module parameters */
 static struct iwl_mod_params iwl4965_mod_params = {
        .num_of_queues = IWL49_NUM_QUEUES,
+       .num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
        .enable_qos = 1,
        .amsdu_size_8K = 1,
        .restart_fw = 1,
@@ -642,6 +650,18 @@ static void iwl4965_gain_computation(struct iwl_priv *priv,
        data->beacon_count = 0;
 }
 
+static void iwl4965_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
+                       __le32 *tx_flags)
+{
+       if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
+               *tx_flags |= TX_CMD_FLG_RTS_MSK;
+               *tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+       } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
+               *tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+               *tx_flags |= TX_CMD_FLG_CTS_MSK;
+       }
+}
+
 static void iwl4965_bg_txpower_work(struct work_struct *work)
 {
        struct iwl_priv *priv = container_of(work, struct iwl_priv,
@@ -1931,9 +1951,11 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
 {
        int ret = 0;
 
-       if (IWL49_FIRST_AMPDU_QUEUE > txq_id) {
-               IWL_WARNING("queue number too small: %d, must be > %d\n",
-                               txq_id, IWL49_FIRST_AMPDU_QUEUE);
+       if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
+               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IWL49_FIRST_AMPDU_QUEUE,
+                       IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1);
                return -EINVAL;
        }
 
@@ -2000,9 +2022,13 @@ static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
        int ret;
        u16 ra_tid;
 
-       if (IWL49_FIRST_AMPDU_QUEUE > txq_id)
-               IWL_WARNING("queue number too small: %d, must be > %d\n",
-                       txq_id, IWL49_FIRST_AMPDU_QUEUE);
+       if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES <= txq_id)) {
+               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IWL49_FIRST_AMPDU_QUEUE,
+                       IWL49_FIRST_AMPDU_QUEUE + IWL49_NUM_AMPDU_QUEUES - 1);
+               return -EINVAL;
+       }
 
        ra_tid = BUILD_RAxTID(sta_id, tid);
 
@@ -2372,6 +2398,7 @@ static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
        .build_addsta_hcmd = iwl4965_build_addsta_hcmd,
        .chain_noise_reset = iwl4965_chain_noise_reset,
        .gain_computation = iwl4965_gain_computation,
+       .rts_tx_cmd_flag = iwl4965_rts_tx_cmd_flag,
 };
 
 static struct iwl_lib_ops iwl4965_lib = {
@@ -2434,6 +2461,9 @@ struct iwl_cfg iwl4965_agn_cfg = {
        .mod_params = &iwl4965_mod_params,
 };
 
+/* Module firmware */
+MODULE_FIRMWARE("iwlwifi-4965" IWL4965_UCODE_API ".ucode");
+
 module_param_named(antenna, iwl4965_mod_params.antenna, int, 0444);
 MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
 module_param_named(disable, iwl4965_mod_params.disable, int, 0444);
index 4efe0c06b5b268ebfb4aeb15852dbd4b134a795b..17d4f31c59345ce9c2883ef01afd44820bb1d931 100644 (file)
@@ -81,6 +81,7 @@
 #define IWL50_QUEUE_SIZE                 256
 #define IWL50_CMD_FIFO_NUM                 7
 #define IWL50_NUM_QUEUES                  20
+#define IWL50_NUM_AMPDU_QUEUES           10
 #define IWL50_FIRST_AMPDU_QUEUE                  10
 
 #define IWL_sta_id_POS 12
index 717db0d5ffb3a84112ef4ce6ff41cc9d8bc90ba3..878d6193b232d71c541afa4680b5cd3396a6de45 100644 (file)
@@ -370,6 +370,16 @@ static void iwl5000_chain_noise_reset(struct iwl_priv *priv)
        }
 }
 
+static void iwl5000_rts_tx_cmd_flag(struct ieee80211_tx_info *info,
+                       __le32 *tx_flags)
+{
+       if ((info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) ||
+           (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT))
+               *tx_flags |= TX_CMD_FLG_RTS_CTS_MSK;
+       else
+               *tx_flags &= ~TX_CMD_FLG_RTS_CTS_MSK;
+}
+
 static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
        .min_nrg_cck = 95,
        .max_nrg_cck = 0,
@@ -1006,9 +1016,13 @@ static int iwl5000_txq_agg_enable(struct iwl_priv *priv, int txq_id,
        int ret;
        u16 ra_tid;
 
-       if (IWL50_FIRST_AMPDU_QUEUE > txq_id)
-               IWL_WARNING("queue number too small: %d, must be > %d\n",
-                       txq_id, IWL50_FIRST_AMPDU_QUEUE);
+       if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
+               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IWL50_FIRST_AMPDU_QUEUE,
+                       IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1);
+               return -EINVAL;
+       }
 
        ra_tid = BUILD_RAxTID(sta_id, tid);
 
@@ -1067,9 +1081,11 @@ static int iwl5000_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
 {
        int ret;
 
-       if (IWL50_FIRST_AMPDU_QUEUE > txq_id) {
-               IWL_WARNING("queue number too small: %d, must be > %d\n",
-                               txq_id, IWL50_FIRST_AMPDU_QUEUE);
+       if ((IWL50_FIRST_AMPDU_QUEUE > txq_id) ||
+           (IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES <= txq_id)) {
+               IWL_WARNING("queue number out of range: %d, must be %d to %d\n",
+                       txq_id, IWL50_FIRST_AMPDU_QUEUE,
+                       IWL50_FIRST_AMPDU_QUEUE + IWL50_NUM_AMPDU_QUEUES - 1);
                return -EINVAL;
        }
 
@@ -1437,6 +1453,7 @@ static struct iwl_hcmd_utils_ops iwl5000_hcmd_utils = {
        .build_addsta_hcmd = iwl5000_build_addsta_hcmd,
        .gain_computation = iwl5000_gain_computation,
        .chain_noise_reset = iwl5000_chain_noise_reset,
+       .rts_tx_cmd_flag = iwl5000_rts_tx_cmd_flag,
 };
 
 static struct iwl_lib_ops iwl5000_lib = {
@@ -1490,6 +1507,7 @@ static struct iwl_ops iwl5000_ops = {
 
 static struct iwl_mod_params iwl50_mod_params = {
        .num_of_queues = IWL50_NUM_QUEUES,
+       .num_of_ampdu_queues = IWL50_NUM_AMPDU_QUEUES,
        .enable_qos = 1,
        .amsdu_size_8K = 1,
        .restart_fw = 1,
@@ -1506,6 +1524,24 @@ struct iwl_cfg iwl5300_agn_cfg = {
        .mod_params = &iwl50_mod_params,
 };
 
+struct iwl_cfg iwl5100_bg_cfg = {
+       .name = "5100BG",
+       .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+       .sku = IWL_SKU_G,
+       .ops = &iwl5000_ops,
+       .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+       .mod_params = &iwl50_mod_params,
+};
+
+struct iwl_cfg iwl5100_abg_cfg = {
+       .name = "5100ABG",
+       .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
+       .sku = IWL_SKU_A|IWL_SKU_G,
+       .ops = &iwl5000_ops,
+       .eeprom_size = IWL_5000_EEPROM_IMG_SIZE,
+       .mod_params = &iwl50_mod_params,
+};
+
 struct iwl_cfg iwl5100_agn_cfg = {
        .name = "5100AGN",
        .fw_name = "iwlwifi-5000" IWL5000_UCODE_API ".ucode",
index fe05d60ebe63fa78ec15894b639581110e7c9892..e9bb1de0ce3f344b695b949f37bad7bcc03963bb 100644 (file)
@@ -556,6 +556,8 @@ enum {
 #define RXON_FLG_CHANNEL_MODE_MSK              __constant_cpu_to_le32(0x3 << 25)
 #define RXON_FLG_CHANNEL_MODE_PURE_40_MSK      __constant_cpu_to_le32(0x1 << 25)
 #define RXON_FLG_CHANNEL_MODE_MIXED_MSK                __constant_cpu_to_le32(0x2 << 25)
+/* CTS to self (if spec allows) flag */
+#define RXON_FLG_SELF_CTS_EN                   __constant_cpu_to_le32(0x1<<30)
 
 /* rx_config filter flags */
 /* accept all data frames */
@@ -723,7 +725,7 @@ struct iwl4965_csa_notification {
  * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
  * value, to cap the CW value.
  */
-struct iwl4965_ac_qos {
+struct iwl_ac_qos {
        __le16 cw_min;
        __le16 cw_max;
        u8 aifsn;
@@ -745,9 +747,9 @@ struct iwl4965_ac_qos {
  * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
  * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
  */
-struct iwl4965_qosparam_cmd {
+struct iwl_qosparam_cmd {
        __le32 qos_flags;
-       struct iwl4965_ac_qos ac[AC_NUM];
+       struct iwl_ac_qos ac[AC_NUM];
 } __attribute__ ((packed));
 
 /******************************************************************************
@@ -1139,6 +1141,11 @@ struct iwl4965_rx_mpdu_res_start {
 
 /* REPLY_TX Tx flags field */
 
+/* 1: Use RTS/CTS protocol or CTS-to-self if spec alows it
+ * before this frame. if CTS-to-self required check
+ * RXON_FLG_SELF_CTS_EN status. */
+#define TX_CMD_FLG_RTS_CTS_MSK __constant_cpu_to_le32(1 << 0)
+
 /* 1: Use Request-To-Send protocol before this frame.
  * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK. */
 #define TX_CMD_FLG_RTS_MSK __constant_cpu_to_le32(1 << 1)
@@ -2092,6 +2099,9 @@ struct iwl_ct_kill_config {
  *
  *****************************************************************************/
 
+#define SCAN_CHANNEL_TYPE_PASSIVE __constant_cpu_to_le32(0)
+#define SCAN_CHANNEL_TYPE_ACTIVE  __constant_cpu_to_le32(1)
+
 /**
  * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
  *
@@ -2115,12 +2125,12 @@ struct iwl_scan_channel {
        /*
         * type is defined as:
         * 0:0 1 = active, 0 = passive
-        * 1:4 SSID direct bit map; if a bit is set, then corresponding
+        * 1:20 SSID direct bit map; if a bit is set, then corresponding
         *     SSID IE is transmitted in probe request.
-        * 5:7 reserved
+        * 21:31 reserved
         */
-       u8 type;
-       u8 channel;     /* band is selected by iwl4965_scan_cmd "flags" field */
+       __le32 type;
+       __le16 channel; /* band is selected by iwl_scan_cmd "flags" field */
        u8 tx_gain;             /* gain for analog radio */
        u8 dsp_atten;           /* gain for DSP */
        __le16 active_dwell;    /* in 1024-uSec TU (time units), typ 5-50 */
@@ -2140,9 +2150,9 @@ struct iwl_ssid_ie {
        u8 ssid[32];
 } __attribute__ ((packed));
 
-#define PROBE_OPTION_MAX        0x4
+#define PROBE_OPTION_MAX               0x14
 #define TX_CMD_LIFE_TIME_INFINITE      __constant_cpu_to_le32(0xFFFFFFFF)
-#define IWL_GOOD_CRC_TH                __constant_cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH                        __constant_cpu_to_le16(1)
 #define IWL_MAX_SCAN_SIZE 1024
 
 /*
@@ -2919,7 +2929,7 @@ struct iwl5000_calibration_chain_noise_gain_cmd {
  * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
  * this command turns it on or off, or sets up a periodic blinking cycle.
  */
-struct iwl4965_led_cmd {
+struct iwl_led_cmd {
        __le32 interval;        /* "interval" in uSec */
        u8 id;                  /* 1: Activity, 2: Link, 3: Tech */
        u8 off;                 /* # intervals off while blinking;
index eee220cf52a252a9294b20834347628f68cd01bb..a44188bf4459dcb299edea84988e08139ef5514a 100644 (file)
@@ -825,7 +825,7 @@ int iwl_setup_mac(struct iwl_priv *priv)
        hw->queues = 4;
        /* queues to support 11n aggregation */
        if (priv->cfg->sku & IWL_SKU_N)
-               hw->ampdu_queues = 12;
+               hw->ampdu_queues = priv->cfg->mod_params->num_of_ampdu_queues;
 
        hw->conf.beacon_int = 100;
 
index dafd62c7dfd6881afa16a1daeda3f78a30cfb736..db66114f1e5668e88b565c457c885e4cd88125b7 100644 (file)
@@ -70,7 +70,7 @@ struct iwl_host_cmd;
 struct iwl_cmd;
 
 
-#define IWLWIFI_VERSION "1.2.26k"
+#define IWLWIFI_VERSION "1.3.27k"
 #define DRV_COPYRIGHT  "Copyright(c) 2003-2008 Intel Corporation"
 
 #define IWL_PCI_DEVICE(dev, subdev, cfg) \
@@ -93,6 +93,8 @@ struct iwl_hcmd_utils_ops {
                        u16 min_average_noise_antennat_i,
                        u32 min_average_noise);
        void (*chain_noise_reset)(struct iwl_priv *priv);
+       void (*rts_tx_cmd_flag)(struct ieee80211_tx_info *info,
+                       __le32 *tx_flags);
 };
 
 struct iwl_lib_ops {
@@ -157,6 +159,7 @@ struct iwl_mod_params {
        int debug;              /* def: 0 = minimal debug log messages */
        int disable_hw_scan;    /* def: 0 = use h/w scan */
        int num_of_queues;      /* def: HW dependent */
+       int num_of_ampdu_queues;/* def: HW dependent */
        int enable_qos;         /* def: 1 = use quality of service */
        int disable_11n;        /* def: 0 = disable 11n capabilities */
        int amsdu_size_8K;      /* def: 1 = enable 8K amsdu size */
index c8d3d97cf48db021309a89990015e4242050949a..4d789e353e3a76ab840f792ea6eb56b57fdc2644 100644 (file)
@@ -51,12 +51,8 @@ extern struct iwl_cfg iwl4965_agn_cfg;
 extern struct iwl_cfg iwl5300_agn_cfg;
 extern struct iwl_cfg iwl5100_agn_cfg;
 extern struct iwl_cfg iwl5350_agn_cfg;
-
-/* Change firmware file name, using "-" and incrementing number,
- *   *only* when uCode interface or architecture changes so that it
- *   is not compatible with earlier drivers.
- * This number will also appear in << 8 position of 1st dword of uCode file */
-#define IWL4965_UCODE_API "-1"
+extern struct iwl_cfg iwl5100_bg_cfg;
+extern struct iwl_cfg iwl5100_abg_cfg;
 
 /* CT-KILL constants */
 #define CT_KILL_THRESHOLD      110 /* in Celsius */
@@ -280,7 +276,7 @@ struct iwl_cmd {
        struct iwl_cmd_header hdr;      /* uCode API */
        union {
                struct iwl_addsta_cmd addsta;
-               struct iwl4965_led_cmd led;
+               struct iwl_led_cmd led;
                u32 flags;
                u8 val8;
                u16 val16;
@@ -288,7 +284,7 @@ struct iwl_cmd {
                struct iwl4965_bt_cmd bt;
                struct iwl4965_rxon_time_cmd rxon_time;
                struct iwl4965_powertable_cmd powertable;
-               struct iwl4965_qosparam_cmd qosparam;
+               struct iwl_qosparam_cmd qosparam;
                struct iwl_tx_cmd tx;
                struct iwl4965_tx_beacon_cmd tx_beacon;
                struct iwl4965_rxon_assoc_cmd rxon_assoc;
@@ -433,7 +429,7 @@ struct iwl_ht_info {
        u8 non_GF_STA_present;
 };
 
-union iwl4965_qos_capabity {
+union iwl_qos_capabity {
        struct {
                u8 edca_count:4;        /* bit 0-3 */
                u8 q_ack:1;             /* bit 4 */
@@ -454,11 +450,11 @@ union iwl4965_qos_capabity {
 };
 
 /* QoS structures */
-struct iwl4965_qos_info {
+struct iwl_qos_info {
        int qos_enable;
        int qos_active;
-       union iwl4965_qos_capabity qos_cap;
-       struct iwl4965_qosparam_cmd def_qos_parm;
+       union iwl_qos_capabity qos_cap;
+       struct iwl_qosparam_cmd def_qos_parm;
 };
 
 #define STA_PS_STATUS_WAKE             0
@@ -490,8 +486,6 @@ struct iwl_ucode {
        u8 data[0];             /* data in same order as "size" elements */
 };
 
-#define IWL_IBSS_MAC_HASH_SIZE 32
-
 struct iwl4965_ibss_seq {
        u8 mac[ETH_ALEN];
        u16 seq_num;
@@ -933,7 +927,7 @@ struct iwl_priv {
 #endif
 
 #ifdef CONFIG_IWLWIFI_LEDS
-       struct iwl4965_led led[IWL_LED_TRG_MAX];
+       struct iwl_led led[IWL_LED_TRG_MAX];
        unsigned long last_blink_time;
        u8 last_blink_rate;
        u8 allow_blinking;
@@ -1042,7 +1036,7 @@ struct iwl_priv {
        u16 assoc_capability;
        u8 ps_mode;
 
-       struct iwl4965_qos_info qos_data;
+       struct iwl_qos_info qos_data;
 
        struct workqueue_struct *workqueue;
 
@@ -1065,7 +1059,6 @@ struct iwl_priv {
        struct delayed_work init_alive_start;
        struct delayed_work alive_start;
        struct delayed_work scan_check;
-       struct delayed_work post_associate;
        /* TX Power */
        s8 tx_power_user_lmt;
        s8 tx_power_channel_lmt;
index aa6ad18494ce8243ce2c0f12107ca69d912063b2..899d7a2567a8dd42045f6753ec72c6e86208902f 100644 (file)
 #include "iwl-io.h"
 #include "iwl-helpers.h"
 
-#define IWL_1MB_RATE (128 * 1024)
-#define IWL_LED_THRESHOLD (16)
-#define IWL_MAX_BLINK_TBL (10)
+#ifdef CONFIG_IWLWIFI_DEBUG
+static const char *led_type_str[] = {
+       __stringify(IWL_LED_TRG_TX),
+       __stringify(IWL_LED_TRG_RX),
+       __stringify(IWL_LED_TRG_ASSOC),
+       __stringify(IWL_LED_TRG_RADIO),
+       NULL
+};
+#endif /* CONFIG_IWLWIFI_DEBUG */
+
 
 static const struct {
        u16 tpt;
        u8 on_time;
-       u8 of_time;
+       u8 off_time;
 } blink_tbl[] =
 {
        {300, 25, 25},
@@ -63,26 +70,31 @@ static const struct {
        {15, 95, 95 },
        {10, 110, 110},
        {5, 130, 130},
-       {0, 167, 167}
+       {0, 167, 167},
+/* SOLID_ON */
+       {-1, IWL_LED_SOLID, 0}
 };
 
-static int iwl_led_cmd_callback(struct iwl_priv *priv,
-                               struct iwl_cmd *cmd, struct sk_buff *skb)
+#define IWL_1MB_RATE (128 * 1024)
+#define IWL_LED_THRESHOLD (16)
+#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */
+#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
+
+/*  [0-256] -> [0..8] FIXME: we need [0..10] */
+static inline int iwl_brightness_to_idx(enum led_brightness brightness)
 {
-       return 1;
+       return fls(0x000000FF & (u32)brightness);
 }
 
-
 /* Send led command */
-static int iwl_send_led_cmd(struct iwl_priv *priv,
-                           struct iwl4965_led_cmd *led_cmd)
+static int iwl_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
 {
        struct iwl_host_cmd cmd = {
                .id = REPLY_LEDS_CMD,
-               .len = sizeof(struct iwl4965_led_cmd),
+               .len = sizeof(struct iwl_led_cmd),
                .data = led_cmd,
                .meta.flags = CMD_ASYNC,
-               .meta.u.callback = iwl_led_cmd_callback
+               .meta.u.callback = NULL,
        };
        u32 reg;
 
@@ -93,33 +105,20 @@ static int iwl_send_led_cmd(struct iwl_priv *priv,
        return iwl_send_cmd(priv, &cmd);
 }
 
-
-/* Set led on command */
-static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
-{
-       struct iwl4965_led_cmd led_cmd = {
-               .id = led_id,
-               .on = IWL_LED_SOLID,
-               .off = 0,
-               .interval = IWL_DEF_LED_INTRVL
-       };
-       return iwl_send_led_cmd(priv, &led_cmd);
-}
-
-/* Set led on command */
+/* Set led pattern command */
 static int iwl4965_led_pattern(struct iwl_priv *priv, int led_id,
-                              enum led_brightness brightness)
+                              unsigned int idx)
 {
-       struct iwl4965_led_cmd led_cmd = {
+       struct iwl_led_cmd led_cmd = {
                .id = led_id,
-               .on = brightness,
-               .off = brightness,
                .interval = IWL_DEF_LED_INTRVL
        };
-       if (brightness == LED_FULL) {
-               led_cmd.on = IWL_LED_SOLID;
-               led_cmd.off = 0;
-       }
+
+       BUG_ON(idx > IWL_MAX_BLINK_TBL);
+
+       led_cmd.on = blink_tbl[idx].on_time;
+       led_cmd.off = blink_tbl[idx].off_time;
+
        return iwl_send_led_cmd(priv, &led_cmd);
 }
 
@@ -132,10 +131,22 @@ static int iwl4965_led_on_reg(struct iwl_priv *priv, int led_id)
 }
 
 #if 0
+/* Set led on command */
+static int iwl4965_led_on(struct iwl_priv *priv, int led_id)
+{
+       struct iwl_led_cmd led_cmd = {
+               .id = led_id,
+               .on = IWL_LED_SOLID,
+               .off = 0,
+               .interval = IWL_DEF_LED_INTRVL
+       };
+       return iwl_send_led_cmd(priv, &led_cmd);
+}
+
 /* Set led off command */
 int iwl4965_led_off(struct iwl_priv *priv, int led_id)
 {
-       struct iwl4965_led_cmd led_cmd = {
+       struct iwl_led_cmd led_cmd = {
                .id = led_id,
                .on = 0,
                .off = 0,
@@ -155,25 +166,10 @@ static int iwl4965_led_off_reg(struct iwl_priv *priv, int led_id)
        return 0;
 }
 
-/* Set led blink command */
-static int iwl4965_led_not_solid(struct iwl_priv *priv, int led_id,
-                              u8 brightness)
-{
-       struct iwl4965_led_cmd led_cmd = {
-               .id = led_id,
-               .on = brightness,
-               .off = brightness,
-               .interval = IWL_DEF_LED_INTRVL
-       };
-
-       return iwl_send_led_cmd(priv, &led_cmd);
-}
-
-
 /*
  * brightness call back function for Tx/Rx LED
  */
-static int iwl4965_led_associated(struct iwl_priv *priv, int led_id)
+static int iwl_led_associated(struct iwl_priv *priv, int led_id)
 {
        if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
            !test_bit(STATUS_READY, &priv->status))
@@ -189,16 +185,18 @@ static int iwl4965_led_associated(struct iwl_priv *priv, int led_id)
 /*
  * brightness call back for association and radio
  */
-static void iwl4965_led_brightness_set(struct led_classdev *led_cdev,
+static void iwl_led_brightness_set(struct led_classdev *led_cdev,
                                       enum led_brightness brightness)
 {
-       struct iwl4965_led *led = container_of(led_cdev,
-                                              struct iwl4965_led, led_dev);
+       struct iwl_led *led = container_of(led_cdev, struct iwl_led, led_dev);
        struct iwl_priv *priv = led->priv;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
+
+       IWL_DEBUG_LED("Led type = %s brightness = %d\n",
+                       led_type_str[led->type], brightness);
        switch (brightness) {
        case LED_FULL:
                if (led->type == IWL_LED_TRG_ASSOC)
@@ -215,8 +213,10 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev,
                        led->led_off(priv, IWL_LED_LINK);
                break;
        default:
-               if (led->led_pattern)
-                       led->led_pattern(priv, IWL_LED_LINK, brightness);
+               if (led->led_pattern) {
+                       int idx = iwl_brightness_to_idx(brightness);
+                       led->led_pattern(priv, IWL_LED_LINK, idx);
+               }
                break;
        }
 }
@@ -226,8 +226,7 @@ static void iwl4965_led_brightness_set(struct led_classdev *led_cdev,
 /*
  * Register led class with the system
  */
-static int iwl_leds_register_led(struct iwl_priv *priv,
-                                  struct iwl4965_led *led,
+static int iwl_leds_register_led(struct iwl_priv *priv, struct iwl_led *led,
                                   enum led_type type, u8 set_led,
                                   const char *name, char *trigger)
 {
@@ -235,7 +234,7 @@ static int iwl_leds_register_led(struct iwl_priv *priv,
        int ret;
 
        led->led_dev.name = name;
-       led->led_dev.brightness_set = iwl4965_led_brightness_set;
+       led->led_dev.brightness_set = iwl_led_brightness_set;
        led->led_dev.default_trigger = trigger;
 
        led->priv = priv;
@@ -259,32 +258,28 @@ static int iwl_leds_register_led(struct iwl_priv *priv,
 /*
  * calculate blink rate according to last 2 sec Tx/Rx activities
  */
-static inline u8 get_blink_rate(struct iwl_priv *priv)
+static int iwl_get_blink_rate(struct iwl_priv *priv)
 {
        int i;
-       u8 blink_rate;
-       u64 current_tpt = priv->tx_stats[2].bytes + priv->rx_stats[2].bytes;
+       u64 current_tpt = priv->tx_stats[2].bytes;
+       /* FIXME: + priv->rx_stats[2].bytes; */
        s64 tpt = current_tpt - priv->led_tpt;
 
        if (tpt < 0) /* wrapparound */
                tpt = -tpt;
 
+       IWL_DEBUG_LED("tpt %lld current_tpt %lld\n", tpt, current_tpt);
        priv->led_tpt = current_tpt;
 
-       if (tpt < IWL_LED_THRESHOLD) {
+       if (!priv->allow_blinking)
                i = IWL_MAX_BLINK_TBL;
-       } else {
+       else
                for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
                        if (tpt  > (blink_tbl[i].tpt * IWL_1MB_RATE))
                                break;
-       }
-       /* if 0 frame is transfered */
-       if ((i == IWL_MAX_BLINK_TBL) || !priv->allow_blinking)
-               blink_rate = IWL_LED_SOLID;
-       else
-               blink_rate = blink_tbl[i].on_time;
 
-       return blink_rate;
+       IWL_DEBUG_LED("LED BLINK IDX=%d", i);
+       return i;
 }
 
 static inline int is_rf_kill(struct iwl_priv *priv)
@@ -300,7 +295,7 @@ static inline int is_rf_kill(struct iwl_priv *priv)
  */
 void iwl_leds_background(struct iwl_priv *priv)
 {
-       u8 blink_rate;
+       u8 blink_idx;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
                priv->last_blink_time = 0;
@@ -313,9 +308,10 @@ void iwl_leds_background(struct iwl_priv *priv)
 
        if (!priv->allow_blinking) {
                priv->last_blink_time = 0;
-               if (priv->last_blink_rate != IWL_LED_SOLID) {
-                       priv->last_blink_rate = IWL_LED_SOLID;
-                       iwl4965_led_on(priv, IWL_LED_LINK);
+               if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
+                       priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
+                       iwl4965_led_pattern(priv, IWL_LED_LINK,
+                                           IWL_SOLID_BLINK_IDX);
                }
                return;
        }
@@ -324,21 +320,14 @@ void iwl_leds_background(struct iwl_priv *priv)
                        msecs_to_jiffies(1000)))
                return;
 
-       blink_rate = get_blink_rate(priv);
+       blink_idx = iwl_get_blink_rate(priv);
 
        /* call only if blink rate change */
-       if (blink_rate != priv->last_blink_rate) {
-               if (blink_rate != IWL_LED_SOLID) {
-                       priv->last_blink_time = jiffies +
-                                               msecs_to_jiffies(1000);
-                       iwl4965_led_not_solid(priv, IWL_LED_LINK, blink_rate);
-               } else {
-                       priv->last_blink_time = 0;
-                       iwl4965_led_on(priv, IWL_LED_LINK);
-               }
-       }
+       if (blink_idx != priv->last_blink_rate)
+               iwl4965_led_pattern(priv, IWL_LED_LINK, blink_idx);
 
-       priv->last_blink_rate = blink_rate;
+       priv->last_blink_time = jiffies;
+       priv->last_blink_rate = blink_idx;
 }
 EXPORT_SYMBOL(iwl_leds_background);
 
@@ -362,10 +351,8 @@ int iwl_leds_register(struct iwl_priv *priv)
        priv->led[IWL_LED_TRG_RADIO].led_off = iwl4965_led_off_reg;
        priv->led[IWL_LED_TRG_RADIO].led_pattern = NULL;
 
-       ret = iwl_leds_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_RADIO],
-                                  IWL_LED_TRG_RADIO, 1,
-                                  name, trigger);
+       ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RADIO],
+                                  IWL_LED_TRG_RADIO, 1, name, trigger);
        if (ret)
                goto exit_fail;
 
@@ -373,10 +360,9 @@ int iwl_leds_register(struct iwl_priv *priv)
        snprintf(name, sizeof(name), "iwl-%s:assoc",
                 wiphy_name(priv->hw->wiphy));
 
-       ret = iwl_leds_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_ASSOC],
-                                  IWL_LED_TRG_ASSOC, 0,
-                                  name, trigger);
+       ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_ASSOC],
+                                  IWL_LED_TRG_ASSOC, 0, name, trigger);
+
        /* for assoc always turn led on */
        priv->led[IWL_LED_TRG_ASSOC].led_on = iwl4965_led_on_reg;
        priv->led[IWL_LED_TRG_ASSOC].led_off = iwl4965_led_on_reg;
@@ -386,31 +372,26 @@ int iwl_leds_register(struct iwl_priv *priv)
                goto exit_fail;
 
        trigger = ieee80211_get_rx_led_name(priv->hw);
-       snprintf(name, sizeof(name), "iwl-%s:RX",
-                wiphy_name(priv->hw->wiphy));
+       snprintf(name, sizeof(name), "iwl-%s:RX", wiphy_name(priv->hw->wiphy));
 
 
-       ret = iwl_leds_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_RX],
-                                  IWL_LED_TRG_RX, 0,
-                                  name, trigger);
+       ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_RX],
+                                  IWL_LED_TRG_RX, 0, name, trigger);
 
-       priv->led[IWL_LED_TRG_RX].led_on = iwl4965_led_associated;
-       priv->led[IWL_LED_TRG_RX].led_off = iwl4965_led_associated;
+       priv->led[IWL_LED_TRG_RX].led_on = iwl_led_associated;
+       priv->led[IWL_LED_TRG_RX].led_off = iwl_led_associated;
        priv->led[IWL_LED_TRG_RX].led_pattern = iwl4965_led_pattern;
 
        if (ret)
                goto exit_fail;
 
        trigger = ieee80211_get_tx_led_name(priv->hw);
-       snprintf(name, sizeof(name), "iwl-%s:TX",
-                wiphy_name(priv->hw->wiphy));
-       ret = iwl_leds_register_led(priv,
-                                  &priv->led[IWL_LED_TRG_TX],
-                                  IWL_LED_TRG_TX, 0,
-                                  name, trigger);
-       priv->led[IWL_LED_TRG_TX].led_on = iwl4965_led_associated;
-       priv->led[IWL_LED_TRG_TX].led_off = iwl4965_led_associated;
+       snprintf(name, sizeof(name), "iwl-%s:TX", wiphy_name(priv->hw->wiphy));
+       ret = iwl_leds_register_led(priv, &priv->led[IWL_LED_TRG_TX],
+                                  IWL_LED_TRG_TX, 0, name, trigger);
+
+       priv->led[IWL_LED_TRG_TX].led_on = iwl_led_associated;
+       priv->led[IWL_LED_TRG_TX].led_off = iwl_led_associated;
        priv->led[IWL_LED_TRG_TX].led_pattern = iwl4965_led_pattern;
 
        if (ret)
@@ -425,7 +406,7 @@ exit_fail:
 EXPORT_SYMBOL(iwl_leds_register);
 
 /* unregister led class */
-static void iwl_leds_unregister_led(struct iwl4965_led *led, u8 set_led)
+static void iwl_leds_unregister_led(struct iwl_led *led, u8 set_led)
 {
        if (!led->registered)
                return;
index 5bb04128cd65d35b09ee4584619988cbed2077e3..1980ae5a7e8297aadf36418518030ce09bf5a089 100644 (file)
@@ -49,14 +49,13 @@ enum led_type {
 };
 
 
-struct iwl4965_led {
+struct iwl_led {
        struct iwl_priv *priv;
        struct led_classdev led_dev;
 
        int (*led_on) (struct iwl_priv *priv, int led_id);
        int (*led_off) (struct iwl_priv *priv, int led_id);
-       int (*led_pattern) (struct iwl_priv *priv, int led_id,
-                           enum led_brightness brightness);
+       int (*led_pattern) (struct iwl_priv *priv, int led_id, unsigned int idx);
 
        enum led_type type;
        unsigned int registered;
index 3e8500ecf5988fc5d96d12ef76ca9835f0dcf806..e2d9afba38a5b003278c9cfa718f4a4b445a7580 100644 (file)
@@ -29,6 +29,7 @@
 
 #include <linux/etherdevice.h>
 #include <net/mac80211.h>
+#include <asm/unaligned.h>
 #include "iwl-eeprom.h"
 #include "iwl-dev.h"
 #include "iwl-core.h"
@@ -829,23 +830,22 @@ static void iwl_add_radiotap(struct iwl_priv *priv,
        iwl4965_rt->rt_hdr.it_pad = 0;
 
        /* total header + data */
-       put_unaligned(cpu_to_le16(sizeof(*iwl4965_rt)),
-                     &iwl4965_rt->rt_hdr.it_len);
+       put_unaligned_le16(sizeof(*iwl4965_rt), &iwl4965_rt->rt_hdr.it_len);
 
        /* Indicate all the fields we add to the radiotap header */
-       put_unaligned(cpu_to_le32((1 << IEEE80211_RADIOTAP_TSFT) |
-                                 (1 << IEEE80211_RADIOTAP_FLAGS) |
-                                 (1 << IEEE80211_RADIOTAP_RATE) |
-                                 (1 << IEEE80211_RADIOTAP_CHANNEL) |
-                                 (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
-                                 (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
-                                 (1 << IEEE80211_RADIOTAP_ANTENNA)),
-                     &iwl4965_rt->rt_hdr.it_present);
+       put_unaligned_le32((1 << IEEE80211_RADIOTAP_TSFT) |
+                          (1 << IEEE80211_RADIOTAP_FLAGS) |
+                          (1 << IEEE80211_RADIOTAP_RATE) |
+                          (1 << IEEE80211_RADIOTAP_CHANNEL) |
+                          (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL) |
+                          (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE) |
+                          (1 << IEEE80211_RADIOTAP_ANTENNA),
+                          &(iwl4965_rt->rt_hdr.it_present));
 
        /* Zero the flags, we'll add to them as we go */
        iwl4965_rt->rt_flags = 0;
 
-       put_unaligned(cpu_to_le64(tsf), &iwl4965_rt->rt_tsf);
+       put_unaligned_le64(tsf, &iwl4965_rt->rt_tsf);
 
        iwl4965_rt->rt_dbmsignal = signal;
        iwl4965_rt->rt_dbmnoise = noise;
@@ -853,17 +853,14 @@ static void iwl_add_radiotap(struct iwl_priv *priv,
        /* Convert the channel frequency and set the flags */
        put_unaligned(cpu_to_le16(stats->freq), &iwl4965_rt->rt_channelMHz);
        if (!(phy_flags_hw & RX_RES_PHY_FLAGS_BAND_24_MSK))
-               put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
-                                         IEEE80211_CHAN_5GHZ),
-                             &iwl4965_rt->rt_chbitmask);
+               put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_5GHZ,
+                                  &iwl4965_rt->rt_chbitmask);
        else if (phy_flags_hw & RX_RES_PHY_FLAGS_MOD_CCK_MSK)
-               put_unaligned(cpu_to_le16(IEEE80211_CHAN_CCK |
-                                         IEEE80211_CHAN_2GHZ),
-                             &iwl4965_rt->rt_chbitmask);
+               put_unaligned_le16(IEEE80211_CHAN_CCK | IEEE80211_CHAN_2GHZ,
+                                  &iwl4965_rt->rt_chbitmask);
        else    /* 802.11g */
-               put_unaligned(cpu_to_le16(IEEE80211_CHAN_OFDM |
-                                         IEEE80211_CHAN_2GHZ),
-                             &iwl4965_rt->rt_chbitmask);
+               put_unaligned_le16(IEEE80211_CHAN_OFDM | IEEE80211_CHAN_2GHZ,
+                                  &iwl4965_rt->rt_chbitmask);
 
        if (rate == -1)
                iwl4965_rt->rt_rate = 0;
index 5b420b43af5cb8b067ed5354eec768e002b65b00..efc750d2fc5ca988c7fbf5df3686da883b396422 100644 (file)
 /* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
  * sending probe req.  This should be set long enough to hear probe responses
  * from more than one AP.  */
-#define IWL_ACTIVE_DWELL_TIME_24    (20)       /* all times in msec */
-#define IWL_ACTIVE_DWELL_TIME_52    (10)
+#define IWL_ACTIVE_DWELL_TIME_24    (30)       /* all times in msec */
+#define IWL_ACTIVE_DWELL_TIME_52    (20)
+
+#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
+#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
 
 /* For faster active scanning, scan will move to the next channel if fewer than
  * PLCP_QUIET_THRESH packets are heard on this channel within
@@ -48,7 +51,7 @@
  * no other traffic).
  * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
 #define IWL_PLCP_QUIET_THRESH       __constant_cpu_to_le16(1)  /* packets */
-#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(5)  /* msec */
+#define IWL_ACTIVE_QUIET_TIME       __constant_cpu_to_le16(10)  /* msec */
 
 /* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
  * Must be set longer than active dwell time.
 #define IWL_PASSIVE_DWELL_BASE      (100)
 #define IWL_CHANNEL_TUNE_TIME       5
 
+#define IWL_SCAN_PROBE_MASK(n)         cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+
+
 static int scan_tx_ant[3] = {
        RATE_MCS_ANT_A_MSK, RATE_MCS_ANT_B_MSK, RATE_MCS_ANT_C_MSK
 };
 
+
+
 static int iwl_is_empty_essid(const char *essid, int essid_len)
 {
        /* Single white space is for Linksys APs */
@@ -226,8 +234,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
                       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
                       notif->channel,
                       notif->band ? "bg" : "a",
-                      notif->tsf_high,
-                      notif->tsf_low, notif->status, notif->beacon_timer);
+                      le32_to_cpu(notif->tsf_high),
+                      le32_to_cpu(notif->tsf_low),
+                      notif->status, notif->beacon_timer);
 }
 
 /* Service SCAN_RESULTS_NOTIFICATION (0x83) */
@@ -332,19 +341,21 @@ void iwl_setup_rx_scan_handlers(struct iwl_priv *priv)
 EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
 
 static inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
-                                               enum ieee80211_band band)
+                                           enum ieee80211_band band,
+                                           u8 n_probes)
 {
        if (band == IEEE80211_BAND_5GHZ)
-               return IWL_ACTIVE_DWELL_TIME_52;
+               return IWL_ACTIVE_DWELL_TIME_52 +
+                       IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
        else
-               return IWL_ACTIVE_DWELL_TIME_24;
+               return IWL_ACTIVE_DWELL_TIME_24 +
+                       IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
 }
 
 static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
-                                         enum ieee80211_band band)
+                                     enum ieee80211_band band)
 {
-       u16 active = iwl_get_active_dwell_time(priv, band);
-       u16 passive = (band != IEEE80211_BAND_5GHZ) ?
+       u16 passive = (band == IEEE80211_BAND_2GHZ) ?
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
            IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
 
@@ -358,15 +369,12 @@ static u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
                passive = (passive * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
        }
 
-       if (passive <= active)
-               passive = active + 1;
-
        return passive;
 }
 
 static int iwl_get_channels_for_scan(struct iwl_priv *priv,
                                     enum ieee80211_band band,
-                                    u8 is_active, u8 direct_mask,
+                                    u8 is_active, u8 n_probes,
                                     struct iwl_scan_channel *scan_ch)
 {
        const struct ieee80211_channel *channels = NULL;
@@ -375,6 +383,7 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
        u16 passive_dwell = 0;
        u16 active_dwell = 0;
        int added, i;
+       u16 channel;
 
        sband = iwl_get_hw_mode(priv, band);
        if (!sband)
@@ -382,31 +391,35 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
 
        channels = sband->channels;
 
-       active_dwell = iwl_get_active_dwell_time(priv, band);
+       active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
        passive_dwell = iwl_get_passive_dwell_time(priv, band);
 
+       if (passive_dwell <= active_dwell)
+               passive_dwell = active_dwell + 1;
+
        for (i = 0, added = 0; i < sband->n_channels; i++) {
                if (channels[i].flags & IEEE80211_CHAN_DISABLED)
                        continue;
 
-               scan_ch->channel =
+               channel =
                        ieee80211_frequency_to_channel(channels[i].center_freq);
+               scan_ch->channel = cpu_to_le16(channel);
 
-               ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
+               ch_info = iwl_get_channel_info(priv, band, channel);
                if (!is_channel_valid(ch_info)) {
                        IWL_DEBUG_SCAN("Channel %d is INVALID for this band.\n",
-                                      scan_ch->channel);
+                                       channel);
                        continue;
                }
 
                if (!is_active || is_channel_passive(ch_info) ||
                    (channels[i].flags & IEEE80211_CHAN_PASSIVE_SCAN))
-                       scan_ch->type = 0;
+                       scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
                else
-                       scan_ch->type = 1;
+                       scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
 
-               if (scan_ch->type & 1)
-                       scan_ch->type |= (direct_mask << 1);
+               if ((scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) && n_probes)
+                       scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
 
                scan_ch->active_dwell = cpu_to_le16(active_dwell);
                scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
@@ -414,20 +427,20 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
                /* Set txpower levels to defaults */
                scan_ch->dsp_atten = 110;
 
+               /* NOTE: if we were doing 6Mb OFDM for scans we'd use
+                * power level:
+                * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+                */
                if (band == IEEE80211_BAND_5GHZ)
                        scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
-               else {
+               else
                        scan_ch->tx_gain = ((1 << 5) | (5 << 3));
-                       /* NOTE: if we were doing 6Mb OFDM for scans we'd use
-                        * power level:
-                        * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
-                        */
-               }
 
-               IWL_DEBUG_SCAN("Scanning %d [%s %d]\n",
-                              scan_ch->channel,
-                              (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
-                              (scan_ch->type & 1) ?
+               IWL_DEBUG_SCAN("Scanning ch=%d prob=0x%X [%s %d]\n",
+                              channel, le32_to_cpu(scan_ch->type),
+                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+                               "ACTIVE" : "PASSIVE",
+                              (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
                               active_dwell : passive_dwell);
 
                scan_ch++;
@@ -673,7 +686,7 @@ static u32 iwl_scan_tx_ant(struct iwl_priv *priv, enum ieee80211_band band)
                        break;
                }
        }
-
+       IWL_DEBUG_SCAN("select TX ANT = %c\n", 'A' + ind);
        return scan_tx_ant[ind];
 }
 
@@ -693,7 +706,7 @@ static void iwl_bg_request_scan(struct work_struct *data)
        u32 tx_ant;
        u16 cmd_len;
        enum ieee80211_band band;
-       u8 direct_mask;
+       u8 n_probes = 2;
        u8 rx_chain = 0x7; /* bitmap: ABC chains */
 
        conf = ieee80211_get_hw_conf(priv->hw);
@@ -793,17 +806,16 @@ static void iwl_bg_request_scan(struct work_struct *data)
                scan->direct_scan[0].len = priv->direct_ssid_len;
                memcpy(scan->direct_scan[0].ssid,
                       priv->direct_ssid, priv->direct_ssid_len);
-               direct_mask = 1;
+               n_probes++;
        } else if (!iwl_is_associated(priv) && priv->essid_len) {
                IWL_DEBUG_SCAN("Start direct scan for '%s' (not associated)\n",
                                iwl_escape_essid(priv->essid, priv->essid_len));
                scan->direct_scan[0].id = WLAN_EID_SSID;
                scan->direct_scan[0].len = priv->essid_len;
                memcpy(scan->direct_scan[0].ssid, priv->essid, priv->essid_len);
-               direct_mask = 1;
+               n_probes++;
        } else {
                IWL_DEBUG_SCAN("Start indirect scan.\n");
-               direct_mask = 0;
        }
 
        scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
@@ -860,16 +872,11 @@ static void iwl_bg_request_scan(struct work_struct *data)
        scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
                               RXON_FILTER_BCON_AWARE_MSK);
 
-       if (direct_mask)
-               scan->channel_count =
-                       iwl_get_channels_for_scan(priv, band, 1, /* active */
-                                                 direct_mask,
-                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
-       else
-               scan->channel_count =
-                       iwl_get_channels_for_scan(priv, band, 0, /* passive */
-                                                 direct_mask,
-                               (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+       scan->channel_count =
+               iwl_get_channels_for_scan(priv, band, 1, /* active */
+                       n_probes,
+                       (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
+
        if (scan->channel_count == 0) {
                IWL_DEBUG_SCAN("channel count %d\n", scan->channel_count);
                goto done;
index 0be2a71990b03a6b5882cbe059c309f29c282eee..9b50b1052b09fe6f750c1693b12dfafca4b3f2f6 100644 (file)
@@ -601,13 +601,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv,
                tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
        }
 
-       if (info->flags & IEEE80211_TX_CTL_USE_RTS_CTS) {
-               tx_flags |= TX_CMD_FLG_RTS_MSK;
-               tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-       } else if (info->flags & IEEE80211_TX_CTL_USE_CTS_PROTECT) {
-               tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-               tx_flags |= TX_CMD_FLG_CTS_MSK;
-       }
+       priv->cfg->ops->utils->rts_tx_cmd_flag(info, &tx_flags);
 
        if ((tx_flags & TX_CMD_FLG_RTS_MSK) || (tx_flags & TX_CMD_FLG_CTS_MSK))
                tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
index 1a7d18fea89da7f7dfd576a0b960b0712f34d718..4a22d3fba75b36ff66fff021dfa5adb3f688abf9 100644 (file)
@@ -2035,36 +2035,6 @@ static int iwl3945_send_power_mode(struct iwl3945_priv *priv, u32 mode)
        return rc;
 }
 
-int iwl3945_is_network_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
-{
-       /* Filter incoming packets to determine if they are targeted toward
-        * this network, discarding packets coming from ourselves */
-       switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_IBSS: /* Header: Dest. | Source    | BSSID */
-               /* packets from our adapter are dropped (echo) */
-               if (!compare_ether_addr(header->addr2, priv->mac_addr))
-                       return 0;
-               /* {broad,multi}cast packets to our IBSS go through */
-               if (is_multicast_ether_addr(header->addr1))
-                       return !compare_ether_addr(header->addr3, priv->bssid);
-               /* packets to our adapter go through */
-               return !compare_ether_addr(header->addr1, priv->mac_addr);
-       case IEEE80211_IF_TYPE_STA: /* Header: Dest. | AP{BSSID} | Source */
-               /* packets from our adapter are dropped (echo) */
-               if (!compare_ether_addr(header->addr3, priv->mac_addr))
-                       return 0;
-               /* {broad,multi}cast packets to our BSS go through */
-               if (is_multicast_ether_addr(header->addr1))
-                       return !compare_ether_addr(header->addr2, priv->bssid);
-               /* packets to our adapter go through */
-               return !compare_ether_addr(header->addr1, priv->mac_addr);
-       default:
-               return 1;
-       }
-
-       return 1;
-}
-
 /**
  * iwl3945_scan_cancel - Cancel any currently executing HW scan
  *
@@ -2117,20 +2087,6 @@ static int iwl3945_scan_cancel_timeout(struct iwl3945_priv *priv, unsigned long
        return ret;
 }
 
-static void iwl3945_sequence_reset(struct iwl3945_priv *priv)
-{
-       /* Reset ieee stats */
-
-       /* We don't reset the net_device_stats (ieee->stats) on
-        * re-association */
-
-       priv->last_seq_num = -1;
-       priv->last_frag_num = -1;
-       priv->last_packet_time = 0;
-
-       iwl3945_scan_cancel(priv);
-}
-
 #define MAX_UCODE_BEACON_INTERVAL      1024
 #define INTEL_CONN_LISTEN_INTERVAL     __constant_cpu_to_le16(0xA)
 
@@ -2925,72 +2881,6 @@ void iwl3945_set_decrypted_flag(struct iwl3945_priv *priv, struct sk_buff *skb,
        }
 }
 
-#define IWL_PACKET_RETRY_TIME HZ
-
-int iwl3945_is_duplicate_packet(struct iwl3945_priv *priv, struct ieee80211_hdr *header)
-{
-       u16 sc = le16_to_cpu(header->seq_ctrl);
-       u16 seq = (sc & IEEE80211_SCTL_SEQ) >> 4;
-       u16 frag = sc & IEEE80211_SCTL_FRAG;
-       u16 *last_seq, *last_frag;
-       unsigned long *last_time;
-
-       switch (priv->iw_mode) {
-       case IEEE80211_IF_TYPE_IBSS:{
-               struct list_head *p;
-               struct iwl3945_ibss_seq *entry = NULL;
-               u8 *mac = header->addr2;
-               int index = mac[5] & (IWL_IBSS_MAC_HASH_SIZE - 1);
-
-               __list_for_each(p, &priv->ibss_mac_hash[index]) {
-                       entry = list_entry(p, struct iwl3945_ibss_seq, list);
-                       if (!compare_ether_addr(entry->mac, mac))
-                               break;
-               }
-               if (p == &priv->ibss_mac_hash[index]) {
-                       entry = kzalloc(sizeof(*entry), GFP_ATOMIC);
-                       if (!entry) {
-                               IWL_ERROR("Cannot malloc new mac entry\n");
-                               return 0;
-                       }
-                       memcpy(entry->mac, mac, ETH_ALEN);
-                       entry->seq_num = seq;
-                       entry->frag_num = frag;
-                       entry->packet_time = jiffies;
-                       list_add(&entry->list, &priv->ibss_mac_hash[index]);
-                       return 0;
-               }
-               last_seq = &entry->seq_num;
-               last_frag = &entry->frag_num;
-               last_time = &entry->packet_time;
-               break;
-       }
-       case IEEE80211_IF_TYPE_STA:
-               last_seq = &priv->last_seq_num;
-               last_frag = &priv->last_frag_num;
-               last_time = &priv->last_packet_time;
-               break;
-       default:
-               return 0;
-       }
-       if ((*last_seq == seq) &&
-           time_after(*last_time + IWL_PACKET_RETRY_TIME, jiffies)) {
-               if (*last_frag == frag)
-                       goto drop;
-               if (*last_frag + 1 != frag)
-                       /* out-of-order fragment */
-                       goto drop;
-       } else
-               *last_seq = seq;
-
-       *last_frag = frag;
-       *last_time = jiffies;
-       return 0;
-
- drop:
-       return 1;
-}
-
 #ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
 
 #include "iwl-spectrum.h"
@@ -6531,8 +6421,6 @@ static void iwl3945_bg_post_associate(struct work_struct *data)
                break;
        }
 
-       iwl3945_sequence_reset(priv);
-
        iwl3945_activate_qos(priv, 0);
 
        /* we have just associated, don't start scan too early */
@@ -6907,6 +6795,9 @@ static void iwl3945_config_ap(struct iwl3945_priv *priv)
         * clear sta table, add BCAST sta... */
 }
 
+/* temporary */
+static int iwl3945_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+
 static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                                        struct ieee80211_vif *vif,
                                    struct ieee80211_if_conf *conf)
@@ -6924,10 +6815,21 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                return 0;
        }
 
+       /* handle this temporarily here */
+       if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+           conf->changed & IEEE80211_IFCC_BEACON) {
+               struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+               if (!beacon)
+                       return -ENOMEM;
+               rc = iwl3945_mac_beacon_update(hw, beacon);
+               if (rc)
+                       return rc;
+       }
+
        /* XXX: this MUST use conf->mac_addr */
 
        if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
-           (!conf->beacon || !conf->ssid_len)) {
+           (!conf->ssid_len)) {
                IWL_DEBUG_MAC80211
                    ("Leaving in AP mode because HostAPD is not ready.\n");
                return 0;
@@ -6959,7 +6861,7 @@ static int iwl3945_mac_config_interface(struct ieee80211_hw *hw,
                if (priv->ibss_beacon)
                        dev_kfree_skb(priv->ibss_beacon);
 
-               priv->ibss_beacon = conf->beacon;
+               priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
        }
 
        if (iwl3945_is_rfkill(priv))
@@ -7940,7 +7842,6 @@ static struct ieee80211_ops iwl3945_hw_ops = {
        .conf_tx = iwl3945_mac_conf_tx,
        .get_tsf = iwl3945_mac_get_tsf,
        .reset_tsf = iwl3945_mac_reset_tsf,
-       .beacon_update = iwl3945_mac_beacon_update,
        .hw_scan = iwl3945_mac_hw_scan
 };
 
@@ -7950,7 +7851,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        struct iwl3945_priv *priv;
        struct ieee80211_hw *hw;
        struct iwl_3945_cfg *cfg = (struct iwl_3945_cfg *)(ent->driver_data);
-       int i;
        unsigned long flags;
        DECLARE_MAC_BUF(mac);
 
@@ -8011,9 +7911,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
        spin_lock_init(&priv->sta_lock);
        spin_lock_init(&priv->hcmd_lock);
 
-       for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++)
-               INIT_LIST_HEAD(&priv->ibss_mac_hash[i]);
-
        INIT_LIST_HEAD(&priv->free_frames);
 
        mutex_init(&priv->mutex);
@@ -8186,8 +8083,6 @@ static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
 static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 {
        struct iwl3945_priv *priv = pci_get_drvdata(pdev);
-       struct list_head *p, *q;
-       int i;
        unsigned long flags;
 
        if (!priv)
@@ -8208,14 +8103,6 @@ static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
 
        iwl_synchronize_irq(priv);
 
-       /* Free MAC hash list for ADHOC */
-       for (i = 0; i < IWL_IBSS_MAC_HASH_SIZE; i++) {
-               list_for_each_safe(p, q, &priv->ibss_mac_hash[i]) {
-                       list_del(p);
-                       kfree(list_entry(p, struct iwl3945_ibss_seq, list));
-               }
-       }
-
        sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
 
        iwl3945_rfkill_unregister(priv);
index 7f65d9123b2ac01944f0cff56c947a2608b99a3c..71f5da3fe5c41e5908f25ca9145bba04aa67ad60 100644 (file)
@@ -250,6 +250,9 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
 
        /* always get timestamp with Rx frame */
        priv->staging_rxon.flags |= RXON_FLG_TSF2HOST_MSK;
+       /* allow CTS-to-self if possible. this is relevant only for
+        * 5000, but will not damage 4965 */
+       priv->staging_rxon.flags |= RXON_FLG_SELF_CTS_EN;
 
        ret = iwl4965_check_rxon_cmd(&priv->staging_rxon);
        if (ret) {
@@ -325,16 +328,6 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
        if (!priv->error_recovering)
                priv->start_calib = 0;
 
-       iwl_init_sensitivity(priv);
-
-       /* If we issue a new RXON command which required a tune then we must
-        * send a new TXPOWER command or we won't be able to Tx any frames */
-       ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-       if (ret) {
-               IWL_ERROR("Error sending TX power (%d)\n", ret);
-               return ret;
-       }
-
        /* Add the broadcast address so we can send broadcast frames */
        if (iwl_rxon_add_station(priv, iwl_bcast_addr, 0) ==
                                                IWL_INVALID_STATION) {
@@ -370,6 +363,16 @@ static int iwl4965_commit_rxon(struct iwl_priv *priv)
                memcpy(active_rxon, &priv->staging_rxon, sizeof(*active_rxon));
        }
 
+       iwl_init_sensitivity(priv);
+
+       /* If we issue a new RXON command which required a tune then we must
+        * send a new TXPOWER command or we won't be able to Tx any frames */
+       ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+       if (ret) {
+               IWL_ERROR("Error sending TX power (%d)\n", ret);
+               return ret;
+       }
+
        return 0;
 }
 
@@ -572,25 +575,14 @@ static void iwl4965_ht_conf(struct iwl_priv *priv,
 /*
  * QoS  support
 */
-static int iwl4965_send_qos_params_command(struct iwl_priv *priv,
-                                      struct iwl4965_qosparam_cmd *qos)
-{
-
-       return iwl_send_cmd_pdu(priv, REPLY_QOS_PARAM,
-                               sizeof(struct iwl4965_qosparam_cmd), qos);
-}
-
-static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
+static void iwl_activate_qos(struct iwl_priv *priv, u8 force)
 {
-       unsigned long flags;
-
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
 
        if (!priv->qos_data.qos_enable)
                return;
 
-       spin_lock_irqsave(&priv->lock, flags);
        priv->qos_data.def_qos_parm.qos_flags = 0;
 
        if (priv->qos_data.qos_cap.q_AP.queue_request &&
@@ -604,15 +596,14 @@ static void iwl4965_activate_qos(struct iwl_priv *priv, u8 force)
        if (priv->current_ht_config.is_ht)
                priv->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
        if (force || iwl_is_associated(priv)) {
                IWL_DEBUG_QOS("send QoS cmd with Qos active=%d FLAGS=0x%X\n",
                                priv->qos_data.qos_active,
                                priv->qos_data.def_qos_parm.qos_flags);
 
-               iwl4965_send_qos_params_command(priv,
-                               &(priv->qos_data.def_qos_parm));
+               iwl_send_cmd_pdu_async(priv, REPLY_QOS_PARAM,
+                                      sizeof(struct iwl_qosparam_cmd),
+                                      &priv->qos_data.def_qos_parm, NULL);
        }
 }
 
@@ -2421,6 +2412,7 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
        struct ieee80211_conf *conf = NULL;
        int ret = 0;
        DECLARE_MAC_BUF(mac);
+       unsigned long flags;
 
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP) {
                IWL_ERROR("%s Should not be called in AP mode\n", __FUNCTION__);
@@ -2510,25 +2502,15 @@ static void iwl4965_post_associate(struct iwl_priv *priv)
        if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS)
                priv->assoc_station_added = 1;
 
-       iwl4965_activate_qos(priv, 0);
+       spin_lock_irqsave(&priv->lock, flags);
+       iwl_activate_qos(priv, 0);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        iwl_power_update_mode(priv, 0);
        /* we have just associated, don't start scan too early */
        priv->next_scan_jiffies = jiffies + IWL_DELAY_NEXT_SCAN;
 }
 
-
-static void iwl4965_bg_post_associate(struct work_struct *data)
-{
-       struct iwl_priv *priv = container_of(data, struct iwl_priv,
-                                            post_associate.work);
-
-       mutex_lock(&priv->mutex);
-       iwl4965_post_associate(priv);
-       mutex_unlock(&priv->mutex);
-
-}
-
 static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf);
 
 static void iwl_bg_scan_completed(struct work_struct *work)
@@ -2659,7 +2641,6 @@ static void iwl4965_mac_stop(struct ieee80211_hw *hw)
                 */
                mutex_lock(&priv->mutex);
                iwl_scan_cancel_timeout(priv, 100);
-               cancel_delayed_work(&priv->post_associate);
                mutex_unlock(&priv->mutex);
        }
 
@@ -2855,6 +2836,7 @@ out:
 static void iwl4965_config_ap(struct iwl_priv *priv)
 {
        int ret = 0;
+       unsigned long flags;
 
        if (test_bit(STATUS_EXIT_PENDING, &priv->status))
                return;
@@ -2902,7 +2884,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
                /* restore RXON assoc */
                priv->staging_rxon.filter_flags |= RXON_FILTER_ASSOC_MSK;
                iwl4965_commit_rxon(priv);
-               iwl4965_activate_qos(priv, 1);
+               spin_lock_irqsave(&priv->lock, flags);
+               iwl_activate_qos(priv, 1);
+               spin_unlock_irqrestore(&priv->lock, flags);
                iwl_rxon_add_station(priv, iwl_bcast_addr, 0);
        }
        iwl4965_send_beacon_cmd(priv);
@@ -2912,6 +2896,9 @@ static void iwl4965_config_ap(struct iwl_priv *priv)
         * clear sta table, add BCAST sta... */
 }
 
+/* temporary */
+static int iwl4965_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb);
+
 static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
                                        struct ieee80211_vif *vif,
                                    struct ieee80211_if_conf *conf)
@@ -2929,8 +2916,18 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
                return 0;
        }
 
+       if (priv->iw_mode == IEEE80211_IF_TYPE_IBSS &&
+           conf->changed & IEEE80211_IFCC_BEACON) {
+               struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+               if (!beacon)
+                       return -ENOMEM;
+               rc = iwl4965_mac_beacon_update(hw, beacon);
+               if (rc)
+                       return rc;
+       }
+
        if ((priv->iw_mode == IEEE80211_IF_TYPE_AP) &&
-           (!conf->beacon || !conf->ssid_len)) {
+           (!conf->ssid_len)) {
                IWL_DEBUG_MAC80211
                    ("Leaving in AP mode because HostAPD is not ready.\n");
                return 0;
@@ -2962,7 +2959,7 @@ static int iwl4965_mac_config_interface(struct ieee80211_hw *hw,
                if (priv->ibss_beacon)
                        dev_kfree_skb(priv->ibss_beacon);
 
-               priv->ibss_beacon = conf->beacon;
+               priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
        }
 
        if (iwl_is_rfkill(priv))
@@ -3048,7 +3045,6 @@ static void iwl4965_mac_remove_interface(struct ieee80211_hw *hw,
 
        if (iwl_is_ready_rf(priv)) {
                iwl_scan_cancel_timeout(priv, 100);
-               cancel_delayed_work(&priv->post_associate);
                priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
                iwl4965_commit_rxon(priv);
        }
@@ -3338,15 +3334,12 @@ static int iwl4965_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
        priv->qos_data.def_qos_parm.ac[q].reserved1 = 0;
        priv->qos_data.qos_active = 1;
 
-       spin_unlock_irqrestore(&priv->lock, flags);
-
-       mutex_lock(&priv->mutex);
        if (priv->iw_mode == IEEE80211_IF_TYPE_AP)
-               iwl4965_activate_qos(priv, 1);
+               iwl_activate_qos(priv, 1);
        else if (priv->assoc_id && iwl_is_associated(priv))
-               iwl4965_activate_qos(priv, 0);
+               iwl_activate_qos(priv, 0);
 
-       mutex_unlock(&priv->mutex);
+       spin_unlock_irqrestore(&priv->lock, flags);
 
        IWL_DEBUG_MAC80211("leave\n");
        return 0;
@@ -3413,8 +3406,6 @@ static void iwl4965_mac_reset_tsf(struct ieee80211_hw *hw)
 
        iwl_reset_qos(priv);
 
-       cancel_delayed_work(&priv->post_associate);
-
        spin_lock_irqsave(&priv->lock, flags);
        priv->assoc_id = 0;
        priv->assoc_capability = 0;
@@ -4016,7 +4007,6 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
        INIT_WORK(&priv->beacon_update, iwl4965_bg_beacon_update);
        INIT_WORK(&priv->set_monitor, iwl4965_bg_set_monitor);
        INIT_WORK(&priv->run_time_calib_work, iwl_bg_run_time_calib_work);
-       INIT_DELAYED_WORK(&priv->post_associate, iwl4965_bg_post_associate);
        INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
        INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
 
@@ -4043,7 +4033,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
        cancel_delayed_work_sync(&priv->init_alive_start);
        cancel_delayed_work(&priv->scan_check);
        cancel_delayed_work(&priv->alive_start);
-       cancel_delayed_work(&priv->post_associate);
        cancel_work_sync(&priv->beacon_update);
        del_timer_sync(&priv->statistics_periodic);
 }
@@ -4090,7 +4079,6 @@ static struct ieee80211_ops iwl4965_hw_ops = {
        .get_tx_stats = iwl4965_mac_get_tx_stats,
        .conf_tx = iwl4965_mac_conf_tx,
        .reset_tsf = iwl4965_mac_reset_tsf,
-       .beacon_update = iwl4965_mac_beacon_update,
        .bss_info_changed = iwl4965_bss_info_changed,
        .ampdu_action = iwl4965_mac_ampdu_action,
        .hw_scan = iwl4965_mac_hw_scan
@@ -4409,8 +4397,16 @@ static struct pci_device_id iwl_hw_card_ids[] = {
        {IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
        {IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
 #ifdef CONFIG_IWL5000
-       {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1205, iwl5100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1305, iwl5100_bg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1206, iwl5100_abg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1306, iwl5100_abg_cfg)},
+       {IWL_PCI_DEVICE(0x4232, 0x1326, iwl5100_abg_cfg)},
+       {IWL_PCI_DEVICE(0x4237, 0x1216, iwl5100_abg_cfg)},
        {IWL_PCI_DEVICE(0x4232, PCI_ANY_ID, iwl5100_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4235, PCI_ANY_ID, iwl5300_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4236, PCI_ANY_ID, iwl5300_agn_cfg)},
+       {IWL_PCI_DEVICE(0x4237, PCI_ANY_ID, iwl5100_agn_cfg)},
        {IWL_PCI_DEVICE(0x423A, PCI_ANY_ID, iwl5350_agn_cfg)},
 #endif /* CONFIG_IWL5000 */
        {0}
index 5d30c57e3969cfe4ed4d65da9d57d0f9728122ca..913dc9fe08f9a242b35d46412511e34a5c098e81 100644 (file)
@@ -126,7 +126,7 @@ static void mac80211_hwsim_monitor_rx(struct ieee80211_hw *hw,
                                          (1 << IEEE80211_RADIOTAP_CHANNEL));
        hdr->rt_flags = 0;
        hdr->rt_rate = txrate->bitrate / 5;
-       hdr->rt_channel = data->channel->center_freq;
+       hdr->rt_channel = cpu_to_le16(data->channel->center_freq);
        flags = IEEE80211_CHAN_2GHZ;
        if (txrate->flags & IEEE80211_RATE_ERP_G)
                flags |= IEEE80211_CHAN_OFDM;
index 91cbd9e560bd93ff28983156b90c992f07f6d0aa..4c0538d6099bb2503646d091e4a9e9a1d3417095 100644 (file)
@@ -1069,6 +1069,40 @@ static void rt2400pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 /*
  * TX data initialization
  */
+static void rt2400pci_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       u32 word;
+       u32 reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
+       /*
+        * Replace rt2x00lib allocated descriptor with the
+        * pointer to the _real_ hardware descriptor.
+        * After that, map the beacon to DMA and update the
+        * descriptor.
+        */
+       memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len);
+       skbdesc->desc = entry_priv->desc;
+
+       rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+
+       rt2x00_desc_read(entry_priv->desc, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+       rt2x00_desc_write(entry_priv->desc, 1, word);
+}
+
 static void rt2400pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
                                    const enum data_queue_qid queue)
 {
@@ -1515,59 +1549,6 @@ static u64 rt2400pci_get_tsf(struct ieee80211_hw *hw)
        return tsf;
 }
 
-static int rt2400pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       struct queue_entry_priv_pci *entry_priv;
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-       u32 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-       entry_priv = intf->beacon->priv_data;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       intf->beacon->skb = skb;
-       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->desc = entry_priv->desc;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
-
-       /*
-        * Enable beacon generation.
-        * Write entire beacon with descriptor to register,
-        * and kick the beacon generator.
-        */
-       rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
-       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
-       rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
-
-       return 0;
-}
-
 static int rt2400pci_tx_last_beacon(struct ieee80211_hw *hw)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1592,7 +1573,6 @@ static const struct ieee80211_ops rt2400pci_mac80211_ops = {
        .conf_tx                = rt2400pci_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt2400pci_get_tsf,
-       .beacon_update          = rt2400pci_beacon_update,
        .tx_last_beacon         = rt2400pci_tx_last_beacon,
 };
 
@@ -1610,6 +1590,7 @@ static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
        .link_tuner             = rt2400pci_link_tuner,
        .write_tx_desc          = rt2400pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
+       .write_beacon           = rt2400pci_write_beacon,
        .kick_tx_queue          = rt2400pci_kick_tx_queue,
        .fill_rxdone            = rt2400pci_fill_rxdone,
        .config_filter          = rt2400pci_config_filter,
index 0f2a0e22fd713c2227f92f8cba87527658934ff6..aa6dfb811c7181bf861b04b7e35c062820581831 100644 (file)
@@ -1227,6 +1227,40 @@ static void rt2500pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 /*
  * TX data initialization
  */
+static void rt2500pci_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct queue_entry_priv_pci *entry_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       u32 word;
+       u32 reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
+       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
+       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
+       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
+       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
+       /*
+        * Replace rt2x00lib allocated descriptor with the
+        * pointer to the _real_ hardware descriptor.
+        * After that, map the beacon to DMA and update the
+        * descriptor.
+        */
+       memcpy(entry_priv->desc, skbdesc->desc, skbdesc->desc_len);
+       skbdesc->desc = entry_priv->desc;
+
+       rt2x00queue_map_txskb(rt2x00dev, entry->skb);
+
+       rt2x00_desc_read(entry_priv->desc, 1, &word);
+       rt2x00_set_field32(&word, TXD_W1_BUFFER_ADDRESS, skbdesc->skb_dma);
+       rt2x00_desc_write(entry_priv->desc, 1, word);
+}
+
 static void rt2500pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
                                    const enum data_queue_qid queue)
 {
@@ -1808,60 +1842,6 @@ static u64 rt2500pci_get_tsf(struct ieee80211_hw *hw)
        return tsf;
 }
 
-static int rt2500pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       struct queue_entry_priv_pci *entry_priv;
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-       u32 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       entry_priv = intf->beacon->priv_data;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       intf->beacon->skb = skb;
-       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->desc = entry_priv->desc;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-       rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 0);
-       rt2x00_set_field32(&reg, CSR14_TBCN, 0);
-       rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
-       rt2x00pci_register_write(rt2x00dev, CSR14, reg);
-
-       /*
-        * Enable beacon generation.
-        * Write entire beacon with descriptor to register,
-        * and kick the beacon generator.
-        */
-       rt2x00queue_map_txskb(rt2x00dev, intf->beacon->skb);
-       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
-       rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
-
-       return 0;
-}
-
 static int rt2500pci_tx_last_beacon(struct ieee80211_hw *hw)
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
@@ -1886,7 +1866,6 @@ static const struct ieee80211_ops rt2500pci_mac80211_ops = {
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt2500pci_get_tsf,
-       .beacon_update          = rt2500pci_beacon_update,
        .tx_last_beacon         = rt2500pci_tx_last_beacon,
 };
 
@@ -1904,6 +1883,7 @@ static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
        .link_tuner             = rt2500pci_link_tuner,
        .write_tx_desc          = rt2500pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
+       .write_beacon           = rt2500pci_write_beacon,
        .kick_tx_queue          = rt2500pci_kick_tx_queue,
        .fill_rxdone            = rt2500pci_fill_rxdone,
        .config_filter          = rt2500pci_config_filter,
index 367db10b96d923046807b91232251976589620d8..3558cb210747a1b6ba6f8cde0962f925747e9eab 100644 (file)
@@ -1107,6 +1107,65 @@ static void rt2500usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_desc_write(txd, 0, word);
 }
 
+/*
+ * TX data initialization
+ */
+static void rt2500usb_beacondone(struct urb *urb);
+
+static void rt2500usb_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
+       struct queue_entry_priv_usb_bcn *bcn_priv = entry->priv_data;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       int pipe = usb_sndbulkpipe(usb_dev, 1);
+       int length;
+       u16 reg;
+
+       /*
+        * Add the descriptor in front of the skb.
+        */
+       skb_push(entry->skb, entry->queue->desc_size);
+       memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
+       skbdesc->desc = entry->skb->data;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
+       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
+       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
+
+       /*
+        * USB devices cannot blindly pass the skb->len as the
+        * length of the data to usb_fill_bulk_urb. Pass the skb
+        * to the driver to determine what the length should be.
+        */
+       length = rt2x00dev->ops->lib->get_tx_data_len(rt2x00dev, entry->skb);
+
+       usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
+                         entry->skb->data, length, rt2500usb_beacondone,
+                         entry);
+
+       /*
+        * Second we need to create the guardian byte.
+        * We only need a single byte, so lets recycle
+        * the 'flags' field we are not using for beacons.
+        */
+       bcn_priv->guardian_data = 0;
+       usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
+                         &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
+                         entry);
+
+       /*
+        * Send out the guardian byte.
+        */
+       usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
+}
+
 static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
                                     struct sk_buff *skb)
 {
@@ -1122,9 +1181,6 @@ static int rt2500usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
        return length;
 }
 
-/*
- * TX data initialization
- */
 static void rt2500usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
                                    const enum data_queue_qid queue)
 {
@@ -1679,96 +1735,6 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        return 0;
 }
 
-/*
- * IEEE80211 stack callback functions.
- */
-static int rt2500usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct usb_device *usb_dev = to_usb_device_intf(rt2x00dev->dev);
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       struct queue_entry_priv_usb_bcn *bcn_priv;
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-       int pipe = usb_sndbulkpipe(usb_dev, 1);
-       int length;
-       u16 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       bcn_priv = intf->beacon->priv_data;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       intf->beacon->skb = skb;
-       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
-
-       /*
-        * Add the descriptor in front of the skb.
-        */
-       skb_push(skb, intf->beacon->queue->desc_size);
-       memset(skb->data, 0, intf->beacon->queue->desc_size);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->desc = skb->data;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-       rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 0);
-       rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 0);
-       rt2x00_set_field16(&reg, TXRX_CSR19_BEACON_GEN, 0);
-       rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
-
-       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
-
-       /*
-        * USB devices cannot blindly pass the skb->len as the
-        * length of the data to usb_fill_bulk_urb. Pass the skb
-        * to the driver to determine what the length should be.
-        */
-       length = rt2500usb_get_tx_data_len(rt2x00dev, skb);
-
-       usb_fill_bulk_urb(bcn_priv->urb, usb_dev, pipe,
-                         skb->data, length, rt2500usb_beacondone,
-                         intf->beacon);
-
-       /*
-        * Second we need to create the guardian byte.
-        * We only need a single byte, so lets recycle
-        * the 'flags' field we are not using for beacons.
-        */
-       bcn_priv->guardian_data = 0;
-       usb_fill_bulk_urb(bcn_priv->guardian_urb, usb_dev, pipe,
-                         &bcn_priv->guardian_data, 1, rt2500usb_beacondone,
-                         intf->beacon);
-
-       /*
-        * Send out the guardian byte.
-        */
-       usb_submit_urb(bcn_priv->guardian_urb, GFP_ATOMIC);
-
-       /*
-        * Enable beacon generation.
-        */
-       rt2500usb_kick_tx_queue(rt2x00dev, QID_BEACON);
-
-       return 0;
-}
-
 static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
        .start                  = rt2x00mac_start,
@@ -1782,7 +1748,6 @@ static const struct ieee80211_ops rt2500usb_mac80211_ops = {
        .bss_info_changed       = rt2x00mac_bss_info_changed,
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
-       .beacon_update          = rt2500usb_beacon_update,
 };
 
 static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
@@ -1797,6 +1762,7 @@ static const struct rt2x00lib_ops rt2500usb_rt2x00_ops = {
        .link_tuner             = rt2500usb_link_tuner,
        .write_tx_desc          = rt2500usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
+       .write_beacon           = rt2500usb_write_beacon,
        .get_tx_data_len        = rt2500usb_get_tx_data_len,
        .kick_tx_queue          = rt2500usb_kick_tx_queue,
        .fill_rxdone            = rt2500usb_fill_rxdone,
index c07d9ef383f0bc56fcabcc308370614f547a78b3..9fab0df18c3cd032215483717ec6f152f6e8d613 100644 (file)
@@ -364,6 +364,8 @@ struct rt2x00_intf {
 #define DELAYED_UPDATE_BEACON          0x00000001
 #define DELAYED_CONFIG_ERP             0x00000002
 #define DELAYED_LED_ASSOC              0x00000004
+
+       u16 seqno;
 };
 
 static inline struct rt2x00_intf* vif_to_intf(struct ieee80211_vif *vif)
@@ -434,6 +436,7 @@ struct rt2x00lib_conf {
  */
 struct rt2x00lib_erp {
        int short_preamble;
+       int cts_protection;
 
        int ack_timeout;
        int ack_consume_time;
@@ -520,6 +523,7 @@ struct rt2x00lib_ops {
                               struct sk_buff *skb,
                               struct txentry_desc *txdesc);
        int (*write_tx_data) (struct queue_entry *entry);
+       void (*write_beacon) (struct queue_entry *entry);
        int (*get_tx_data_len) (struct rt2x00_dev *rt2x00dev,
                                struct sk_buff *skb);
        void (*kick_tx_queue) (struct rt2x00_dev *rt2x00dev,
@@ -909,39 +913,6 @@ static inline u16 get_duration_res(const unsigned int size, const u8 rate)
  */
 void rt2x00queue_map_txskb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
 
-/**
- * rt2x00queue_create_tx_descriptor - Create TX descriptor from mac80211 input
- * @entry: The entry which will be used to transfer the TX frame.
- * @txdesc: rt2x00 TX descriptor which will be initialized by this function.
- *
- * This function will initialize the &struct txentry_desc based on information
- * from mac80211. This descriptor can then be used by rt2x00lib and the drivers
- * to correctly initialize the hardware descriptor.
- * Note that before calling this function the skb->cb array must be untouched
- * by rt2x00lib. Only after this function completes will it be save to
- * overwrite the skb->cb information.
- * The reason for this is that mac80211 writes its own tx information into
- * the skb->cb array, and this function will use that information to initialize
- * the &struct txentry_desc structure.
- */
-void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
-                                     struct txentry_desc *txdesc);
-
-/**
- * rt2x00queue_write_tx_descriptor - Write TX descriptor to hardware
- * @entry: The entry which will be used to transfer the TX frame.
- * @txdesc: TX descriptor which will be used to write hardware descriptor
- *
- * This function will write a TX descriptor initialized by
- * &rt2x00queue_create_tx_descriptor to the hardware. After this call
- * has completed the frame is now owned by the hardware, the hardware
- * queue will have automatically be kicked unless this frame was generated
- * by rt2x00lib, in which case the frame is "special" and must be kicked
- * by the caller.
- */
-void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
-                                    struct txentry_desc *txdesc);
-
 /**
  * rt2x00queue_get_queue - Convert queue index to queue pointer
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
index 48608e8cc8b4a50ef01a559314e4375e7214c946..f20ca712504f734a39e8d5ee5a2264ad955365f7 100644 (file)
@@ -84,6 +84,8 @@ void rt2x00lib_config_erp(struct rt2x00_dev *rt2x00dev,
        memset(&erp, 0, sizeof(erp));
 
        erp.short_preamble = bss_conf->use_short_preamble;
+       erp.cts_protection = bss_conf->use_cts_prot;
+
        erp.ack_timeout = PLCP + get_duration(ACK_SIZE, 10);
        erp.ack_consume_time = SIFS + PLCP + get_duration(ACK_SIZE, 10);
 
index b48c04e80a3827e8c284e6a396581fa38ee18978..8c93eb8353b0bc4c2b49d47926b5357263ab20ec 100644 (file)
@@ -409,7 +409,6 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
 {
        struct rt2x00_dev *rt2x00dev = data;
        struct rt2x00_intf *intf = vif_to_intf(vif);
-       struct sk_buff *skb;
        struct ieee80211_bss_conf conf;
        int delayed_flags;
 
@@ -435,12 +434,8 @@ static void rt2x00lib_intf_scheduled_iter(void *data, u8 *mac,
        if (!test_bit(DEVICE_ENABLED_RADIO, &rt2x00dev->flags))
                return;
 
-       if (delayed_flags & DELAYED_UPDATE_BEACON) {
-               skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
-               if (skb &&
-                   rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, skb))
-                       dev_kfree_skb(skb);
-       }
+       if (delayed_flags & DELAYED_UPDATE_BEACON)
+               rt2x00queue_update_beacon(rt2x00dev, vif);
 
        if (delayed_flags & DELAYED_CONFIG_ERP)
                rt2x00lib_config_erp(rt2x00dev, intf, &conf);
index b971bc6e7ee260d9f3ca282e806004aeecae2faf..bab05a56e7a0f2f9f2679cb220a72b2fca771775 100644 (file)
@@ -100,6 +100,14 @@ int rt2x00lib_load_firmware(struct rt2x00_dev *rt2x00dev)
        retval = rt2x00dev->ops->lib->load_firmware(rt2x00dev,
                                                    rt2x00dev->fw->data,
                                                    rt2x00dev->fw->size);
+
+       /*
+        * When the firmware is uploaded to the hardware the LED
+        * association status might have been triggered, for correct
+        * LED handling it should now be reset.
+        */
+       rt2x00leds_led_assoc(rt2x00dev, false);
+
        return retval;
 }
 
index eae5ce1d4de3776c411c7d00f784c7a62a3a7c03..f2c9b0e79b5f005bd883cc81c9a80cf725b7c718 100644 (file)
@@ -138,6 +138,14 @@ void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb);
  */
 int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb);
 
+/**
+ * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+                             struct ieee80211_vif *vif);
+
 /**
  * rt2x00queue_index_inc - Index incrementation function
  * @queue: Queue (&struct data_queue) to perform the action on.
index 3a1fb6d47e5d48cddef370ac395ffdf6141ceeac..77af1df5d899f07e0e4abd69ff353eede8128d0d 100644 (file)
@@ -96,6 +96,7 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
        struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
        enum data_queue_qid qid = skb_get_queue_mapping(skb);
+       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
        struct data_queue *queue;
        u16 frame_control;
 
@@ -151,6 +152,18 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
                }
        }
 
+       /*
+        * XXX: This is as wrong as the old mac80211 code was,
+        *      due to beacons not getting sequence numbers assigned
+        *      properly.
+        */
+       if (tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
+               if (tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
+                       intf->seqno += 0x10;
+               ieee80211hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
+               ieee80211hdr->seq_ctrl |= cpu_to_le16(intf->seqno);
+       }
+
        if (rt2x00queue_write_tx_frame(queue, skb)) {
                ieee80211_stop_queue(rt2x00dev->hw, qid);
                return NETDEV_TX_BUSY;
@@ -348,7 +361,8 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
 {
        struct rt2x00_dev *rt2x00dev = hw->priv;
        struct rt2x00_intf *intf = vif_to_intf(vif);
-       int status;
+       int update_bssid = 0;
+       int status = 0;
 
        /*
         * Mac80211 might be calling this function while we are trying
@@ -360,12 +374,13 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
        spin_lock(&intf->lock);
 
        /*
-        * If the interface does not work in master mode,
-        * then the bssid value in the interface structure
-        * should now be set.
+        * conf->bssid can be NULL if coming from the internal
+        * beacon update routine.
         */
-       if (conf->type != IEEE80211_IF_TYPE_AP)
+       if (conf->changed & IEEE80211_IFCC_BSSID && conf->bssid) {
+               update_bssid = 1;
                memcpy(&intf->bssid, conf->bssid, ETH_ALEN);
+       }
 
        spin_unlock(&intf->lock);
 
@@ -375,17 +390,14 @@ int rt2x00mac_config_interface(struct ieee80211_hw *hw,
         * values as arguments we make keep access to rt2x00_intf thread safe
         * even without the lock.
         */
-       rt2x00lib_config_intf(rt2x00dev, intf, conf->type, NULL, conf->bssid);
+       rt2x00lib_config_intf(rt2x00dev, intf, vif->type, NULL,
+                             update_bssid ? conf->bssid : NULL);
 
        /*
-        * We only need to initialize the beacon when master mode is enabled.
+        * Update the beacon.
         */
-       if (conf->type != IEEE80211_IF_TYPE_AP || !conf->beacon)
-               return 0;
-
-       status = rt2x00dev->ops->hw->beacon_update(rt2x00dev->hw, conf->beacon);
-       if (status)
-               dev_kfree_skb(conf->beacon);
+       if (conf->changed & IEEE80211_IFCC_BEACON)
+               status = rt2x00queue_update_beacon(rt2x00dev, vif);
 
        return status;
 }
@@ -501,7 +513,7 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
         * When the erp information has changed, we should perform
         * additional configuration steps. For all other changes we are done.
         */
-       if (changes & BSS_CHANGED_ERP_PREAMBLE) {
+       if (changes & (BSS_CHANGED_ERP_PREAMBLE | BSS_CHANGED_ERP_CTS_PROT)) {
                if (!test_bit(DRIVER_REQUIRE_SCHEDULED, &rt2x00dev->flags))
                        rt2x00lib_config_erp(rt2x00dev, intf, bss_conf);
                else
index 3ddce538ef4af3bcfffddc4fc7ddff9b341d094e..7f442030f5ad187a34b375a7ab4f19fa05c19a7b 100644 (file)
@@ -108,12 +108,15 @@ void rt2x00queue_unmap_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
 
 void rt2x00queue_free_skb(struct rt2x00_dev *rt2x00dev, struct sk_buff *skb)
 {
+       if (!skb)
+               return;
+
        rt2x00queue_unmap_skb(rt2x00dev, skb);
        dev_kfree_skb_any(skb);
 }
 
-void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
-                                     struct txentry_desc *txdesc)
+static void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
+                                            struct txentry_desc *txdesc)
 {
        struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
@@ -237,10 +240,9 @@ void rt2x00queue_create_tx_descriptor(struct queue_entry *entry,
                        txdesc->signal |= 0x08;
        }
 }
-EXPORT_SYMBOL_GPL(rt2x00queue_create_tx_descriptor);
 
-void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
-                                    struct txentry_desc *txdesc)
+static void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
+                                           struct txentry_desc *txdesc)
 {
        struct data_queue *queue = entry->queue;
        struct rt2x00_dev *rt2x00dev = queue->rt2x00dev;
@@ -270,7 +272,6 @@ void rt2x00queue_write_tx_descriptor(struct queue_entry *entry,
            !test_bit(ENTRY_TXD_BURST, &txdesc->flags))
                rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, queue->qid);
 }
-EXPORT_SYMBOL_GPL(rt2x00queue_write_tx_descriptor);
 
 int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
 {
@@ -320,6 +321,60 @@ int rt2x00queue_write_tx_frame(struct data_queue *queue, struct sk_buff *skb)
        return 0;
 }
 
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+                             struct ieee80211_vif *vif)
+{
+       struct rt2x00_intf *intf = vif_to_intf(vif);
+       struct skb_frame_desc *skbdesc;
+       struct txentry_desc txdesc;
+       __le32 desc[16];
+
+       if (unlikely(!intf->beacon))
+               return -ENOBUFS;
+
+       intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
+       if (!intf->beacon->skb)
+               return -ENOMEM;
+
+       /*
+        * Copy all TX descriptor information into txdesc,
+        * after that we are free to use the skb->cb array
+        * for our information.
+        */
+       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
+
+       /*
+        * For the descriptor we use a local array from where the
+        * driver can move it to the correct location required for
+        * the hardware.
+        */
+       memset(desc, 0, sizeof(desc));
+
+       /*
+        * Fill in skb descriptor
+        */
+       skbdesc = get_skb_frame_desc(intf->beacon->skb);
+       memset(skbdesc, 0, sizeof(*skbdesc));
+       skbdesc->desc = desc;
+       skbdesc->desc_len = intf->beacon->queue->desc_size;
+       skbdesc->entry = intf->beacon;
+
+       /*
+        * Write TX descriptor into reserved room in front of the beacon.
+        */
+       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
+
+       /*
+        * Send beacon to hardware.
+        * Also enable beacon generation, which might have been disabled
+        * by the driver during the config_beacon() callback function.
+        */
+       rt2x00dev->ops->lib->write_beacon(intf->beacon);
+       rt2x00dev->ops->lib->kick_tx_queue(rt2x00dev, QID_BEACON);
+
+       return 0;
+}
+
 struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
                                         const enum data_queue_qid queue)
 {
index 5a1330c5de71882a044e349ef906b8c40196be38..70ef7bf434ab44dee46e031999a19e1f7041e311 100644 (file)
@@ -1600,6 +1600,41 @@ static void rt61pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 /*
  * TX data initialization
  */
+static void rt61pci_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       unsigned int beacon_base;
+       u32 reg;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Write entire beacon with descriptor to register.
+        */
+       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       rt2x00pci_register_multiwrite(rt2x00dev,
+                                     beacon_base,
+                                     skbdesc->desc, skbdesc->desc_len);
+       rt2x00pci_register_multiwrite(rt2x00dev,
+                                     beacon_base + skbdesc->desc_len,
+                                     entry->skb->data, entry->skb->len);
+
+       /*
+        * Clean up beacon skb.
+        */
+       dev_kfree_skb_any(entry->skb);
+       entry->skb = NULL;
+}
+
 static void rt61pci_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
                                  const enum data_queue_qid queue)
 {
@@ -2355,72 +2390,6 @@ static u64 rt61pci_get_tsf(struct ieee80211_hw *hw)
        return tsf;
 }
 
-static int rt61pci_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       struct queue_entry_priv_pci *entry_priv;
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-       unsigned int beacon_base;
-       u32 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       intf->beacon->skb = skb;
-       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
-
-       entry_priv = intf->beacon->priv_data;
-       memset(entry_priv->desc, 0, intf->beacon->queue->desc_size);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->desc = entry_priv->desc;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Write entire beacon with descriptor to register,
-        * and kick the beacon generator.
-        */
-       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
-       beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-       rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
-                                     skbdesc->desc, skbdesc->desc_len);
-       rt2x00pci_register_multiwrite(rt2x00dev,
-                                     beacon_base + skbdesc->desc_len,
-                                     skb->data, skb->len);
-       rt61pci_kick_tx_queue(rt2x00dev, QID_BEACON);
-
-       /*
-        * Clean up beacon skb.
-        */
-       dev_kfree_skb_any(skb);
-       intf->beacon->skb = NULL;
-
-       return 0;
-}
-
 static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
        .start                  = rt2x00mac_start,
@@ -2436,7 +2405,6 @@ static const struct ieee80211_ops rt61pci_mac80211_ops = {
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt61pci_get_tsf,
-       .beacon_update          = rt61pci_beacon_update,
 };
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
@@ -2456,6 +2424,7 @@ static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
        .link_tuner             = rt61pci_link_tuner,
        .write_tx_desc          = rt61pci_write_tx_desc,
        .write_tx_data          = rt2x00pci_write_tx_data,
+       .write_beacon           = rt61pci_write_beacon,
        .kick_tx_queue          = rt61pci_kick_tx_queue,
        .fill_rxdone            = rt61pci_fill_rxdone,
        .config_filter          = rt61pci_config_filter,
index 25d8b660051f48aa8c71bdd7db1f377c48a83f97..34c6ff27afc4d5dbc0bcd8a009f3aeab331eb237 100644 (file)
@@ -1343,6 +1343,49 @@ static void rt73usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
        rt2x00_desc_write(txd, 0, word);
 }
 
+/*
+ * TX data initialization
+ */
+static void rt73usb_write_beacon(struct queue_entry *entry)
+{
+       struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+       struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
+       unsigned int beacon_base;
+       u32 reg;
+
+       /*
+        * Add the descriptor in front of the skb.
+        */
+       skb_push(entry->skb, entry->queue->desc_size);
+       memcpy(entry->skb->data, skbdesc->desc, skbdesc->desc_len);
+       skbdesc->desc = entry->skb->data;
+
+       /*
+        * Disable beaconing while we are reloading the beacon data,
+        * otherwise we might be sending out invalid data.
+        */
+       rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
+       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+       /*
+        * Write entire beacon with descriptor to register.
+        */
+       beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+       rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
+                                USB_VENDOR_REQUEST_OUT, beacon_base, 0,
+                                entry->skb->data, entry->skb->len,
+                                REGISTER_TIMEOUT32(entry->skb->len));
+
+       /*
+        * Clean up the beacon skb.
+        */
+       dev_kfree_skb(entry->skb);
+       entry->skb = NULL;
+}
+
 static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
                                   struct sk_buff *skb)
 {
@@ -1358,9 +1401,6 @@ static int rt73usb_get_tx_data_len(struct rt2x00_dev *rt2x00dev,
        return length;
 }
 
-/*
- * TX data initialization
- */
 static void rt73usb_kick_tx_queue(struct rt2x00_dev *rt2x00dev,
                                  const enum data_queue_qid queue)
 {
@@ -1958,73 +1998,6 @@ static u64 rt73usb_get_tsf(struct ieee80211_hw *hw)
 #define rt73usb_get_tsf        NULL
 #endif
 
-static int rt73usb_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-       struct rt2x00_dev *rt2x00dev = hw->priv;
-       struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-       struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
-       struct skb_frame_desc *skbdesc;
-       struct txentry_desc txdesc;
-       unsigned int beacon_base;
-       u32 reg;
-
-       if (unlikely(!intf->beacon))
-               return -ENOBUFS;
-
-       /*
-        * Copy all TX descriptor information into txdesc,
-        * after that we are free to use the skb->cb array
-        * for our information.
-        */
-       intf->beacon->skb = skb;
-       rt2x00queue_create_tx_descriptor(intf->beacon, &txdesc);
-
-       /*
-        * Add the descriptor in front of the skb.
-        */
-       skb_push(skb, intf->beacon->queue->desc_size);
-       memset(skb->data, 0, intf->beacon->queue->desc_size);
-
-       /*
-        * Fill in skb descriptor
-        */
-       skbdesc = get_skb_frame_desc(skb);
-       memset(skbdesc, 0, sizeof(*skbdesc));
-       skbdesc->desc = skb->data;
-       skbdesc->desc_len = intf->beacon->queue->desc_size;
-       skbdesc->entry = intf->beacon;
-
-       /*
-        * Disable beaconing while we are reloading the beacon data,
-        * otherwise we might be sending out invalid data.
-        */
-       rt73usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
-       rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
-       rt73usb_register_write(rt2x00dev, TXRX_CSR9, reg);
-
-       /*
-        * Write entire beacon with descriptor to register,
-        * and kick the beacon generator.
-        */
-       rt2x00queue_write_tx_descriptor(intf->beacon, &txdesc);
-       beacon_base = HW_BEACON_OFFSET(intf->beacon->entry_idx);
-       rt2x00usb_vendor_request(rt2x00dev, USB_MULTI_WRITE,
-                                USB_VENDOR_REQUEST_OUT, beacon_base, 0,
-                                skb->data, skb->len,
-                                REGISTER_TIMEOUT32(skb->len));
-       rt73usb_kick_tx_queue(rt2x00dev, QID_BEACON);
-
-       /*
-        * Clean up the beacon skb.
-        */
-       dev_kfree_skb(skb);
-       intf->beacon->skb = NULL;
-
-       return 0;
-}
-
 static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .tx                     = rt2x00mac_tx,
        .start                  = rt2x00mac_start,
@@ -2040,7 +2013,6 @@ static const struct ieee80211_ops rt73usb_mac80211_ops = {
        .conf_tx                = rt2x00mac_conf_tx,
        .get_tx_stats           = rt2x00mac_get_tx_stats,
        .get_tsf                = rt73usb_get_tsf,
-       .beacon_update          = rt73usb_beacon_update,
 };
 
 static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
@@ -2058,6 +2030,7 @@ static const struct rt2x00lib_ops rt73usb_rt2x00_ops = {
        .link_tuner             = rt73usb_link_tuner,
        .write_tx_desc          = rt73usb_write_tx_desc,
        .write_tx_data          = rt2x00usb_write_tx_data,
+       .write_beacon           = rt73usb_write_beacon,
        .get_tx_data_len        = rt73usb_get_tx_data_len,
        .kick_tx_queue          = rt73usb_kick_tx_queue,
        .fill_rxdone            = rt73usb_fill_rxdone,
index 33527e58256fb439d2f188933ec3b2dd8ec35087..d3067b1216caad08de4b94c03b6eb412e00a0276 100644 (file)
@@ -430,8 +430,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg |
                         RTL818X_CONFIG3_ANAPARAM_WRITE);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
+                         RTL8187_RTL8225_ANAPARAM_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                         RTL8187_RTL8225_ANAPARAM2_ON);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg &
                         ~RTL818X_CONFIG3_ANAPARAM_WRITE);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD,
@@ -453,8 +455,10 @@ static int rtl8187_init_hw(struct ieee80211_hw *dev)
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
                        reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_ON);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
+                         RTL8187_RTL8225_ANAPARAM_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                         RTL8187_RTL8225_ANAPARAM2_ON);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
                        reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
@@ -566,9 +570,12 @@ static int rtl8187b_init_hw(struct ieee80211_hw *dev)
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
        reg |= RTL818X_CONFIG3_ANAPARAM_WRITE | RTL818X_CONFIG3_GNT_SELECT;
        rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, 0x727f3f52);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM, 0x45090658);
-       rtl818x_iowrite8(priv, &priv->map->ANAPARAM3, 0);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                         RTL8187B_RTL8225_ANAPARAM2_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
+                         RTL8187B_RTL8225_ANAPARAM_ON);
+       rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
+                        RTL8187B_RTL8225_ANAPARAM3_ON);
 
        rtl818x_iowrite8(priv, (u8 *)0xFF61, 0x10);
        reg = rtl818x_ioread8(priv, (u8 *)0xFF62);
@@ -1180,7 +1187,7 @@ static struct usb_driver rtl8187_driver = {
        .name           = KBUILD_MODNAME,
        .id_table       = rtl8187_table,
        .probe          = rtl8187_probe,
-       .disconnect     = rtl8187_disconnect,
+       .disconnect     = __devexit_p(rtl8187_disconnect),
 };
 
 static int __init rtl8187_init(void)
index 1e059de971163cecd1db095fdade0cefc8fed72f..1bae8990341096913c6800c19df076ac4f7e208a 100644 (file)
@@ -307,7 +307,8 @@ static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
                        reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                         RTL8187_RTL8225_ANAPARAM2_ON);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
                        reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
@@ -560,7 +561,8 @@ static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
                        reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_ON);
+       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                         RTL8187_RTL8225_ANAPARAM2_ON);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3,
                        reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
@@ -913,8 +915,19 @@ static void rtl8225_rf_stop(struct ieee80211_hw *dev)
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
        reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
        rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM2, RTL8225_ANAPARAM2_OFF);
-       rtl818x_iowrite32(priv, &priv->map->ANAPARAM, RTL8225_ANAPARAM_OFF);
+       if (!priv->is_rtl8187b) {
+               rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                                 RTL8187_RTL8225_ANAPARAM2_OFF);
+               rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
+                                 RTL8187_RTL8225_ANAPARAM_OFF);
+       } else {
+               rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
+                                 RTL8187B_RTL8225_ANAPARAM2_OFF);
+               rtl818x_iowrite32(priv, &priv->map->ANAPARAM,
+                                 RTL8187B_RTL8225_ANAPARAM_OFF);
+               rtl818x_iowrite8(priv, &priv->map->ANAPARAM3,
+                                 RTL8187B_RTL8225_ANAPARAM3_OFF);
+       }
        rtl818x_iowrite8(priv, &priv->map->CONFIG3, reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
        rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
 }
index d39ed0295b6e70887f15954330f6e560a585aa18..20c5b6ead0f6649194984cc8f3f464cae74b24c5 100644 (file)
 #ifndef RTL8187_RTL8225_H
 #define RTL8187_RTL8225_H
 
-#define RTL8225_ANAPARAM_ON    0xa0000a59
-#define RTL8225_ANAPARAM2_ON   0x860c7312
-#define RTL8225_ANAPARAM_OFF   0xa00beb59
-#define RTL8225_ANAPARAM2_OFF  0x840dec11
+#define RTL8187_RTL8225_ANAPARAM_ON    0xa0000a59
+#define RTL8187_RTL8225_ANAPARAM2_ON   0x860c7312
+#define RTL8187_RTL8225_ANAPARAM_OFF   0xa00beb59
+#define RTL8187_RTL8225_ANAPARAM2_OFF  0x840dec11
+
+#define RTL8187B_RTL8225_ANAPARAM_ON   0x45090658
+#define RTL8187B_RTL8225_ANAPARAM2_ON  0x727f3f52
+#define RTL8187B_RTL8225_ANAPARAM3_ON  0x00
+#define RTL8187B_RTL8225_ANAPARAM_OFF  0x55480658
+#define RTL8187B_RTL8225_ANAPARAM2_OFF 0x72003f50
+#define RTL8187B_RTL8225_ANAPARAM3_OFF 0x00
 
 const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *);
 
index feaf43d172498590f20b6cef32d29f9baae7cbcc..fcc532bb6a7efe0a13482458ff9572c854ca37aa 100644 (file)
@@ -728,15 +728,19 @@ static int zd_op_config_interface(struct ieee80211_hw *hw,
        if (mac->type == IEEE80211_IF_TYPE_MESH_POINT ||
            mac->type == IEEE80211_IF_TYPE_IBSS) {
                associated = true;
-               if (conf->beacon) {
-                       r = zd_mac_config_beacon(hw, conf->beacon);
+               if (conf->changed & IEEE80211_IFCC_BEACON) {
+                       struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+
+                       if (!beacon)
+                               return -ENOMEM;
+                       r = zd_mac_config_beacon(hw, beacon);
                        if (r < 0)
                                return r;
                        r = zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
                                        hw->conf.beacon_int);
                        if (r < 0)
                                return r;
-                       kfree_skb(conf->beacon);
+                       kfree_skb(beacon);
                }
        } else
                associated = is_valid_ether_addr(conf->bssid);
@@ -890,17 +894,6 @@ static void zd_op_bss_info_changed(struct ieee80211_hw *hw,
        }
 }
 
-static int zd_op_beacon_update(struct ieee80211_hw *hw,
-                              struct sk_buff *skb)
-{
-       struct zd_mac *mac = zd_hw_mac(hw);
-       zd_mac_config_beacon(hw, skb);
-       kfree_skb(skb);
-       zd_set_beacon_interval(&mac->chip, BCN_MODE_IBSS |
-                                       hw->conf.beacon_int);
-       return 0;
-}
-
 static const struct ieee80211_ops zd_ops = {
        .tx                     = zd_op_tx,
        .start                  = zd_op_start,
@@ -911,7 +904,6 @@ static const struct ieee80211_ops zd_ops = {
        .config_interface       = zd_op_config_interface,
        .configure_filter       = zd_op_configure_filter,
        .bss_info_changed       = zd_op_bss_info_changed,
-       .beacon_update          = zd_op_beacon_update,
 };
 
 struct ieee80211_hw *zd_mac_alloc_hw(struct usb_interface *intf)
index 0fe5a0ded3eac17f4075d2cbdfcfb88153031238..4bf8cade9dbc5fa534963e40fe99de303f54296a 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/spinlock.h>
 #include <linux/pci.h>
 #include <linux/mod_devicetable.h>
+#include <linux/dma-mapping.h>
 
 #include <linux/ssb/ssb_regs.h>
 
index 656442c6b1c3669ee50e3d32ea21f86248f4f475..24a69f6075c2273471e0240ae45e4e9b12f3fcd5 100644 (file)
@@ -115,17 +115,17 @@ enum ieee80211_max_queues {
  * The information provided in this structure is required for QoS
  * transmit queue configuration. Cf. IEEE 802.11 7.3.2.29.
  *
- * @aifs: arbitration interface space [0..255, -1: use default]
- * @cw_min: minimum contention window [will be a value of the form
- *     2^n-1 in the range 1..1023; 0: use default]
+ * @aifs: arbitration interface space [0..255]
+ * @cw_min: minimum contention window [a value of the form
+ *     2^n-1 in the range 1..32767]
  * @cw_max: maximum contention window [like @cw_min]
  * @txop: maximum burst time in units of 32 usecs, 0 meaning disabled
  */
 struct ieee80211_tx_queue_params {
-       s16 aifs;
+       u16 txop;
        u16 cw_min;
        u16 cw_max;
-       u16 txop;
+       u8 aifs;
 };
 
 /**
@@ -239,6 +239,17 @@ struct ieee80211_bss_conf {
  *     is for the whole aggregation.
  * @IEEE80211_TX_STAT_AMPDU_NO_BACK: no block ack was returned,
  *     so consider using block ack request (BAR).
+ * @IEEE80211_TX_CTL_ASSIGN_SEQ: The driver has to assign a sequence
+ *     number to this frame, taking care of not overwriting the fragment
+ *     number and increasing the sequence number only when the
+ *     IEEE80211_TX_CTL_FIRST_FRAGMENT flags is set. mac80211 will properly
+ *     assign sequence numbers to QoS-data frames but cannot do so correctly
+ *     for non-QoS-data and management frames because beacons need them from
+ *     that counter as well and mac80211 cannot guarantee proper sequencing.
+ *     If this flag is set, the driver should instruct the hardware to
+ *     assign a sequence number to the frame or assign one itself. Cf. IEEE
+ *     802.11-2007 7.1.3.4.1 paragraph 3. This flag will always be set for
+ *     beacons always be clear for frames without a sequence number field.
  */
 enum mac80211_tx_control_flags {
        IEEE80211_TX_CTL_REQ_TX_STATUS          = BIT(0),
@@ -265,6 +276,7 @@ enum mac80211_tx_control_flags {
        IEEE80211_TX_STAT_ACK                   = BIT(21),
        IEEE80211_TX_STAT_AMPDU                 = BIT(22),
        IEEE80211_TX_STAT_AMPDU_NO_BACK         = BIT(23),
+       IEEE80211_TX_CTL_ASSIGN_SEQ             = BIT(24),
 };
 
 
@@ -407,11 +419,13 @@ struct ieee80211_rx_status {
  * @IEEE80211_CONF_SHORT_SLOT_TIME: use 802.11g short slot time
  * @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported)
  * @IEEE80211_CONF_SUPPORT_HT_MODE: use 802.11n HT capabilities (if supported)
+ * @IEEE80211_CONF_PS: Enable 802.11 power save mode
  */
 enum ieee80211_conf_flags {
        IEEE80211_CONF_SHORT_SLOT_TIME  = (1<<0),
        IEEE80211_CONF_RADIOTAP         = (1<<1),
        IEEE80211_CONF_SUPPORT_HT_MODE  = (1<<2),
+       IEEE80211_CONF_PS               = (1<<3),
 };
 
 /**
@@ -526,34 +540,39 @@ struct ieee80211_if_init_conf {
        void *mac_addr;
 };
 
+/**
+ * enum ieee80211_if_conf_change - interface config change flags
+ *
+ * @IEEE80211_IFCC_BSSID: The BSSID changed.
+ * @IEEE80211_IFCC_SSID: The SSID changed.
+ * @IEEE80211_IFCC_BEACON: The beacon for this interface changed
+ *     (currently AP and MESH only), use ieee80211_beacon_get().
+ */
+enum ieee80211_if_conf_change {
+       IEEE80211_IFCC_BSSID    = BIT(0),
+       IEEE80211_IFCC_SSID     = BIT(1),
+       IEEE80211_IFCC_BEACON   = BIT(2),
+};
+
 /**
  * struct ieee80211_if_conf - configuration of an interface
  *
- * @type: type of the interface. This is always the same as was specified in
- *     &struct ieee80211_if_init_conf. The type of an interface never changes
- *     during the life of the interface; this field is present only for
- *     convenience.
+ * @changed: parameters that have changed, see &enum ieee80211_if_conf_change.
  * @bssid: BSSID of the network we are associated to/creating.
  * @ssid: used (together with @ssid_len) by drivers for hardware that
  *     generate beacons independently. The pointer is valid only during the
  *     config_interface() call, so copy the value somewhere if you need
  *     it.
  * @ssid_len: length of the @ssid field.
- * @beacon: beacon template. Valid only if @host_gen_beacon_template in
- *     &struct ieee80211_hw is set. The driver is responsible of freeing
- *     the sk_buff.
- * @beacon_control: tx_control for the beacon template, this field is only
- *     valid when the @beacon field was set.
  *
  * This structure is passed to the config_interface() callback of
  * &struct ieee80211_hw.
  */
 struct ieee80211_if_conf {
-       int type;
+       u32 changed;
        u8 *bssid;
        u8 *ssid;
        size_t ssid_len;
-       struct sk_buff *beacon;
 };
 
 /**
@@ -681,15 +700,6 @@ enum ieee80211_tkip_key_type {
  * any particular flags. There are some exceptions to this rule,
  * however, so you are advised to review these flags carefully.
  *
- * @IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE:
- *     The device only needs to be supplied with a beacon template.
- *     If you need the host to generate each beacon then don't use
- *     this flag and call ieee80211_beacon_get() when you need the
- *     next beacon frame. Note that if you set this flag, you must
- *     implement the set_tim() callback for powersave mode to work
- *     properly.
- *     This flag is only relevant for access-point mode.
- *
  * @IEEE80211_HW_RX_INCLUDES_FCS:
  *     Indicates that received frames passed to the stack include
  *     the FCS at the end.
@@ -1149,17 +1159,6 @@ enum ieee80211_ampdu_mlme_action {
  *     function is optional if the firmware/hardware takes full care of
  *     TSF synchronization.
  *
- * @beacon_update: Setup beacon data for IBSS beacons. Unlike access point,
- *     IBSS uses a fixed beacon frame which is configured using this
- *     function.
- *     If the driver returns success (0) from this callback, it owns
- *     the skb. That means the driver is responsible to kfree_skb() it.
- *     The control structure is not dynamically allocated. That means the
- *     driver does not own the pointer and if it needs it somewhere
- *     outside of the context of this function, it must copy it
- *     somewhere else.
- *     This handler is required only for IBSS mode.
- *
  * @tx_last_beacon: Determine whether the last IBSS beacon was sent by us.
  *     This is needed only for IBSS mode and the result of this function is
  *     used to determine whether to reply to Probe Requests.
@@ -1217,8 +1216,6 @@ struct ieee80211_ops {
                            struct ieee80211_tx_queue_stats *stats);
        u64 (*get_tsf)(struct ieee80211_hw *hw);
        void (*reset_tsf)(struct ieee80211_hw *hw);
-       int (*beacon_update)(struct ieee80211_hw *hw,
-                            struct sk_buff *skb);
        int (*tx_last_beacon)(struct ieee80211_hw *hw);
        int (*ampdu_action)(struct ieee80211_hw *hw,
                            enum ieee80211_ampdu_mlme_action action,
index 3f79413192171a94bb75daf0e72b60b536857d7b..c1f4e0d428c0bf75e79f8513e441262a6d28d949 100644 (file)
@@ -318,7 +318,7 @@ static struct attribute_group netstat_group = {
        .attrs  = netstat_attrs,
 };
 
-#ifdef CONFIG_WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT_SYSFS
 /* helper function that does all the locking etc for wireless stats */
 static ssize_t wireless_show(struct device *d, char *buf,
                             ssize_t (*format)(const struct iw_statistics *,
@@ -459,7 +459,7 @@ int netdev_register_kobject(struct net_device *net)
 #ifdef CONFIG_SYSFS
        *groups++ = &netstat_group;
 
-#ifdef CONFIG_WIRELESS_EXT
+#ifdef CONFIG_WIRELESS_EXT_SYSFS
        if (net->wireless_handlers && net->wireless_handlers->get_wireless_stats)
                *groups++ = &wireless_group;
 #endif
index 81087281b031834bae498c77ded78f6081d767c2..8e7ba0e62cf5dcfcda5e278d92777a512175ed8d 100644 (file)
@@ -50,14 +50,11 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
        struct ieee80211_sub_if_data *sdata;
        int err;
 
-       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
-               return -ENODEV;
-
        itype = nl80211_type_to_mac80211_type(type);
        if (itype == IEEE80211_IF_TYPE_INVALID)
                return -EINVAL;
 
-       err = ieee80211_if_add(local->mdev, name, &dev, itype, params);
+       err = ieee80211_if_add(local, name, &dev, itype, params);
        if (err || itype != IEEE80211_IF_TYPE_MNTR || !flags)
                return err;
 
@@ -68,54 +65,41 @@ static int ieee80211_add_iface(struct wiphy *wiphy, char *name,
 
 static int ieee80211_del_iface(struct wiphy *wiphy, int ifindex)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct net_device *dev;
-       char *name;
-
-       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
-               return -ENODEV;
 
        /* we're under RTNL */
        dev = __dev_get_by_index(&init_net, ifindex);
        if (!dev)
-               return 0;
+               return -ENODEV;
 
-       name = dev->name;
+       ieee80211_if_remove(dev);
 
-       return ieee80211_if_remove(local->mdev, name, -1);
+       return 0;
 }
 
 static int ieee80211_change_iface(struct wiphy *wiphy, int ifindex,
                                  enum nl80211_iftype type, u32 *flags,
                                  struct vif_params *params)
 {
-       struct ieee80211_local *local = wiphy_priv(wiphy);
        struct net_device *dev;
        enum ieee80211_if_types itype;
        struct ieee80211_sub_if_data *sdata;
-
-       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED))
-               return -ENODEV;
+       int ret;
 
        /* we're under RTNL */
        dev = __dev_get_by_index(&init_net, ifindex);
        if (!dev)
                return -ENODEV;
 
-       if (netif_running(dev))
-               return -EBUSY;
-
        itype = nl80211_type_to_mac80211_type(type);
        if (itype == IEEE80211_IF_TYPE_INVALID)
                return -EINVAL;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
-       if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
-               return -EOPNOTSUPP;
-
-       ieee80211_if_reinit(dev);
-       ieee80211_if_set_type(dev, itype);
+       ret = ieee80211_if_change_type(sdata, itype);
+       if (ret)
+               return ret;
 
        if (ieee80211_vif_is_mesh(&sdata->vif) && params->mesh_id_len)
                ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
@@ -485,7 +469,7 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata,
 
        kfree(old);
 
-       return ieee80211_if_config_beacon(sdata->dev);
+       return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
 }
 
 static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev,
@@ -539,7 +523,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
        synchronize_rcu();
        kfree(old);
 
-       return ieee80211_if_config_beacon(dev);
+       return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
 }
 
 /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */
index d20d90eead1f95ea90755045a87814fcecb4bb43..ee509f1109e2112209977f11887602154ef12171 100644 (file)
@@ -70,16 +70,6 @@ DEBUGFS_READONLY_FILE(rate_ctrl_alg, 100, "%s",
 
 /* statistics stuff */
 
-static inline int rtnl_lock_local(struct ieee80211_local *local)
-{
-       rtnl_lock();
-       if (unlikely(local->reg_state != IEEE80211_DEV_REGISTERED)) {
-               rtnl_unlock();
-               return -ENODEV;
-       }
-       return 0;
-}
-
 #define DEBUGFS_STATS_FILE(name, buflen, fmt, value...)                        \
        DEBUGFS_READONLY_FILE(stats_ ##name, buflen, fmt, ##value)
 
@@ -96,10 +86,7 @@ static ssize_t format_devstat_counter(struct ieee80211_local *local,
        if (!local->ops->get_stats)
                return -EOPNOTSUPP;
 
-       res = rtnl_lock_local(local);
-       if (res)
-               return res;
-
+       rtnl_lock();
        res = local->ops->get_stats(local_to_hw(local), &stats);
        rtnl_unlock();
        if (!res)
index b2089b2da48a2c6b0f6e963532335558109c4ecb..475f89a8aee109ce243a12869848eb15d270187c 100644 (file)
@@ -156,6 +156,8 @@ static const struct file_operations name##_ops = {                  \
 
 /* common attributes */
 IEEE80211_IF_FILE(drop_unencrypted, drop_unencrypted, DEC);
+IEEE80211_IF_FILE(force_unicast_rateidx, force_unicast_rateidx, DEC);
+IEEE80211_IF_FILE(max_ratectrl_rateidx, max_ratectrl_rateidx, DEC);
 
 /* STA/IBSS attributes */
 IEEE80211_IF_FILE(state, u.sta.state, DEC);
@@ -191,8 +193,6 @@ __IEEE80211_IF_FILE(flags);
 IEEE80211_IF_FILE(num_sta_ps, u.ap.num_sta_ps, ATOMIC);
 IEEE80211_IF_FILE(dtim_count, u.ap.dtim_count, DEC);
 IEEE80211_IF_FILE(num_beacons, u.ap.num_beacons, DEC);
-IEEE80211_IF_FILE(force_unicast_rateidx, u.ap.force_unicast_rateidx, DEC);
-IEEE80211_IF_FILE(max_ratectrl_rateidx, u.ap.max_ratectrl_rateidx, DEC);
 
 static ssize_t ieee80211_if_fmt_num_buffered_multicast(
        const struct ieee80211_sub_if_data *sdata, char *buf, int buflen)
@@ -248,6 +248,9 @@ IEEE80211_IF_WFILE(min_discovery_timeout,
 static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_ADD(drop_unencrypted, sta);
+       DEBUGFS_ADD(force_unicast_rateidx, ap);
+       DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+
        DEBUGFS_ADD(state, sta);
        DEBUGFS_ADD(bssid, sta);
        DEBUGFS_ADD(prev_bssid, sta);
@@ -268,23 +271,29 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata)
 static void add_ap_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_ADD(drop_unencrypted, ap);
+       DEBUGFS_ADD(force_unicast_rateidx, ap);
+       DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+
        DEBUGFS_ADD(num_sta_ps, ap);
        DEBUGFS_ADD(dtim_count, ap);
        DEBUGFS_ADD(num_beacons, ap);
-       DEBUGFS_ADD(force_unicast_rateidx, ap);
-       DEBUGFS_ADD(max_ratectrl_rateidx, ap);
        DEBUGFS_ADD(num_buffered_multicast, ap);
 }
 
 static void add_wds_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_ADD(drop_unencrypted, wds);
+       DEBUGFS_ADD(force_unicast_rateidx, ap);
+       DEBUGFS_ADD(max_ratectrl_rateidx, ap);
+
        DEBUGFS_ADD(peer, wds);
 }
 
 static void add_vlan_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_ADD(drop_unencrypted, vlan);
+       DEBUGFS_ADD(force_unicast_rateidx, ap);
+       DEBUGFS_ADD(max_ratectrl_rateidx, ap);
 }
 
 static void add_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -372,6 +381,9 @@ static void add_files(struct ieee80211_sub_if_data *sdata)
 static void del_sta_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_DEL(drop_unencrypted, sta);
+       DEBUGFS_DEL(force_unicast_rateidx, ap);
+       DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+
        DEBUGFS_DEL(state, sta);
        DEBUGFS_DEL(bssid, sta);
        DEBUGFS_DEL(prev_bssid, sta);
@@ -392,23 +404,29 @@ static void del_sta_files(struct ieee80211_sub_if_data *sdata)
 static void del_ap_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_DEL(drop_unencrypted, ap);
+       DEBUGFS_DEL(force_unicast_rateidx, ap);
+       DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+
        DEBUGFS_DEL(num_sta_ps, ap);
        DEBUGFS_DEL(dtim_count, ap);
        DEBUGFS_DEL(num_beacons, ap);
-       DEBUGFS_DEL(force_unicast_rateidx, ap);
-       DEBUGFS_DEL(max_ratectrl_rateidx, ap);
        DEBUGFS_DEL(num_buffered_multicast, ap);
 }
 
 static void del_wds_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_DEL(drop_unencrypted, wds);
+       DEBUGFS_DEL(force_unicast_rateidx, ap);
+       DEBUGFS_DEL(max_ratectrl_rateidx, ap);
+
        DEBUGFS_DEL(peer, wds);
 }
 
 static void del_vlan_files(struct ieee80211_sub_if_data *sdata)
 {
        DEBUGFS_DEL(drop_unencrypted, vlan);
+       DEBUGFS_DEL(force_unicast_rateidx, ap);
+       DEBUGFS_DEL(max_ratectrl_rateidx, ap);
 }
 
 static void del_monitor_files(struct ieee80211_sub_if_data *sdata)
@@ -458,12 +476,12 @@ static void del_mesh_config(struct ieee80211_sub_if_data *sdata)
 }
 #endif
 
-static void del_files(struct ieee80211_sub_if_data *sdata, int type)
+static void del_files(struct ieee80211_sub_if_data *sdata)
 {
        if (!sdata->debugfsdir)
                return;
 
-       switch (type) {
+       switch (sdata->vif.type) {
        case IEEE80211_IF_TYPE_MESH_POINT:
 #ifdef CONFIG_MAC80211_MESH
                del_mesh_stats(sdata);
@@ -503,29 +521,23 @@ void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata)
        sprintf(buf, "netdev:%s", sdata->dev->name);
        sdata->debugfsdir = debugfs_create_dir(buf,
                sdata->local->hw.wiphy->debugfsdir);
+       add_files(sdata);
 }
 
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata)
 {
-       del_files(sdata, sdata->vif.type);
+       del_files(sdata);
        debugfs_remove(sdata->debugfsdir);
        sdata->debugfsdir = NULL;
 }
 
-void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
-                                     int oldtype)
-{
-       del_files(sdata, oldtype);
-       add_files(sdata);
-}
-
 static int netdev_notify(struct notifier_block *nb,
                         unsigned long state,
                         void *ndev)
 {
        struct net_device *dev = ndev;
        struct dentry *dir;
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata;
        char buf[10+IFNAMSIZ];
 
        if (state != NETDEV_CHANGENAME)
@@ -537,6 +549,8 @@ static int netdev_notify(struct notifier_block *nb,
        if (dev->ieee80211_ptr->wiphy->privid != mac80211_wiphy_privid)
                return 0;
 
+       sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
        sprintf(buf, "netdev:%s", dev->name);
        dir = sdata->debugfsdir;
        if (!debugfs_rename(dir->d_parent, dir, dir->d_parent, buf))
index a690071fde8a0ef130ff5ea49cf2affdcb6f3827..7af731f0b73113182c54756b53aa3b0b88a37e1d 100644 (file)
@@ -6,8 +6,6 @@
 #ifdef CONFIG_MAC80211_DEBUGFS
 void ieee80211_debugfs_add_netdev(struct ieee80211_sub_if_data *sdata);
 void ieee80211_debugfs_remove_netdev(struct ieee80211_sub_if_data *sdata);
-void ieee80211_debugfs_change_if_type(struct ieee80211_sub_if_data *sdata,
-                                    int oldtype);
 void ieee80211_debugfs_netdev_init(void);
 void ieee80211_debugfs_netdev_exit(void);
 #else
@@ -17,9 +15,6 @@ static inline void ieee80211_debugfs_add_netdev(
 static inline void ieee80211_debugfs_remove_netdev(
        struct ieee80211_sub_if_data *sdata)
 {}
-static inline void ieee80211_debugfs_change_if_type(
-       struct ieee80211_sub_if_data *sdata, int oldtype)
-{}
 static inline void ieee80211_debugfs_netdev_init(void)
 {}
 
index 02a8753a4eca5b39dacd69de9968ad7cacf127fa..cbea0154ee3a5ff2a1883e1288ce9aaed2b06810 100644 (file)
@@ -237,8 +237,6 @@ struct ieee80211_if_ap {
        struct sk_buff_head ps_bc_buf;
        atomic_t num_sta_ps; /* number of stations in PS mode */
        int dtim_count;
-       int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
-       int max_ratectrl_rateidx; /* max TX rateidx for rate control */
        int num_beacons; /* number of TXed beacon frames for this BSS */
 };
 
@@ -248,7 +246,6 @@ struct ieee80211_if_wds {
 };
 
 struct ieee80211_if_vlan {
-       struct ieee80211_sub_if_data *ap;
        struct list_head list;
 };
 
@@ -422,8 +419,6 @@ struct ieee80211_sub_if_data {
         */
        u64 basic_rates;
 
-       u16 sequence;
-
        /* Fragment table for host-based reassembly */
        struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
        unsigned int fragment_next;
@@ -432,16 +427,18 @@ struct ieee80211_sub_if_data {
        struct ieee80211_key *keys[NUM_DEFAULT_KEYS];
        struct ieee80211_key *default_key;
 
+       /* BSS configuration for this interface. */
+       struct ieee80211_bss_conf bss_conf;
+
        /*
-        * BSS configuration for this interface.
-        *
-        * FIXME: I feel bad putting this here when we already have a
-        *        bss pointer, but the bss pointer is just wrong when
-        *        you have multiple virtual STA mode interfaces...
-        *        This needs to be fixed.
+        * AP this belongs to: self in AP mode and
+        * corresponding AP in VLAN mode, NULL for
+        * all others (might be needed later in IBSS)
         */
-       struct ieee80211_bss_conf bss_conf;
-       struct ieee80211_if_ap *bss; /* BSS that this device belongs to */
+       struct ieee80211_if_ap *bss;
+
+       int force_unicast_rateidx; /* forced TX rateidx for unicast frames */
+       int max_ratectrl_rateidx; /* max TX rateidx for rate control */
 
        union {
                struct ieee80211_if_ap ap;
@@ -533,8 +530,6 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
        return container_of(p, struct ieee80211_sub_if_data, vif);
 }
 
-#define IEEE80211_DEV_TO_SUB_IF(dev) netdev_priv(dev)
-
 enum {
        IEEE80211_RX_MSG        = 1,
        IEEE80211_TX_STATUS_MSG = 2,
@@ -561,12 +556,6 @@ struct ieee80211_local {
        bool tim_in_locked_section; /* see ieee80211_beacon_get() */
        int tx_headroom; /* required headroom for hardware/radiotap */
 
-       enum {
-               IEEE80211_DEV_UNINITIALIZED = 0,
-               IEEE80211_DEV_REGISTERED,
-               IEEE80211_DEV_UNREGISTERED,
-       } reg_state;
-
        /* Tasklet and skb queue to process calls from IRQ mode. All frames
         * added to skb_queue will be processed, but frames in
         * skb_queue_unreliable may be dropped if the total length of these
@@ -760,6 +749,16 @@ static inline int ieee80211_is_multiqueue(struct ieee80211_local *local)
 #endif
 }
 
+static inline struct ieee80211_sub_if_data *
+IEEE80211_DEV_TO_SUB_IF(struct net_device *dev)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       BUG_ON(!local || local->mdev == dev);
+
+       return netdev_priv(dev);
+}
+
 /* this struct represents 802.11n's RA/TID combination */
 struct ieee80211_ra_tid {
        u8 ra[ETH_ALEN];
@@ -853,10 +852,8 @@ static inline int ieee80211_bssid_match(const u8 *raddr, const u8 *addr)
 
 /* ieee80211.c */
 int ieee80211_hw_config(struct ieee80211_local *local);
-int ieee80211_if_config(struct net_device *dev);
-int ieee80211_if_config_beacon(struct net_device *dev);
+int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed);
 void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx);
-void ieee80211_if_setup(struct net_device *dev);
 u32 ieee80211_handle_ht(struct ieee80211_local *local, int enable_ht,
                        struct ieee80211_ht_info *req_ht_cap,
                        struct ieee80211_ht_bss_info *req_bss_cap);
@@ -883,8 +880,8 @@ int ieee80211_sta_scan_results(struct net_device *dev,
 ieee80211_rx_result ieee80211_sta_rx_scan(
        struct net_device *dev, struct sk_buff *skb,
        struct ieee80211_rx_status *rx_status);
-void ieee80211_rx_bss_list_init(struct net_device *dev);
-void ieee80211_rx_bss_list_deinit(struct net_device *dev);
+void ieee80211_rx_bss_list_init(struct ieee80211_local *local);
+void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local);
 int ieee80211_sta_set_extra_ie(struct net_device *dev, char *ie, size_t len);
 struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
                                        struct sk_buff *skb, u8 *bssid,
@@ -925,17 +922,15 @@ static inline void ieee80211_start_mesh(struct net_device *dev)
 {}
 #endif
 
-/* ieee80211_iface.c */
-int ieee80211_if_add(struct net_device *dev, const char *name,
-                    struct net_device **new_dev, int type,
+/* interface handling */
+void ieee80211_if_setup(struct net_device *dev);
+int ieee80211_if_add(struct ieee80211_local *local, const char *name,
+                    struct net_device **new_dev, enum ieee80211_if_types type,
                     struct vif_params *params);
-void ieee80211_if_set_type(struct net_device *dev, int type);
-void ieee80211_if_reinit(struct net_device *dev);
-void __ieee80211_if_del(struct ieee80211_local *local,
-                       struct ieee80211_sub_if_data *sdata);
-int ieee80211_if_remove(struct net_device *dev, const char *name, int id);
-void ieee80211_if_free(struct net_device *dev);
-void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata);
+int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
+                            enum ieee80211_if_types type);
+void ieee80211_if_remove(struct net_device *dev);
+void ieee80211_remove_interfaces(struct ieee80211_local *local);
 
 /* tx handling */
 void ieee80211_clear_tx_pending(struct ieee80211_local *local);
index eeb16926aa7deb1068ab4d0720b25fc13737c257..610ed1d9893af95b3fda10005f3d6d535c3603ad 100644 (file)
@@ -2,6 +2,7 @@
  * Copyright 2002-2005, Instant802 Networks, Inc.
  * Copyright 2005-2006, Devicescape Software, Inc.
  * Copyright (c) 2006 Jiri Benc <jbenc@suse.cz>
+ * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
 #include "debugfs_netdev.h"
 #include "mesh.h"
 
-void ieee80211_if_sdata_init(struct ieee80211_sub_if_data *sdata)
+/*
+ * Called when the netdev is removed or, by the code below, before
+ * the interface type changes.
+ */
+static void ieee80211_teardown_sdata(struct net_device *dev)
 {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_local *local = sdata->local;
+       struct beacon_data *beacon;
+       struct sk_buff *skb;
+       int flushed;
        int i;
 
-       /* Default values for sub-interface parameters */
-       sdata->drop_unencrypted = 0;
-       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
-               skb_queue_head_init(&sdata->fragments[i].skb_list);
-
-       INIT_LIST_HEAD(&sdata->key_list);
-}
+       ieee80211_debugfs_remove_netdev(sdata);
 
-static void ieee80211_if_sdata_deinit(struct ieee80211_sub_if_data *sdata)
-{
-       int i;
+       /* free extra data */
+       ieee80211_free_keys(sdata);
 
        for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
                __skb_queue_purge(&sdata->fragments[i].skb_list);
-}
-
-/* Must be called with rtnl lock held. */
-int ieee80211_if_add(struct net_device *dev, const char *name,
-                    struct net_device **new_dev, int type,
-                    struct vif_params *params)
-{
-       struct net_device *ndev;
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata = NULL;
-       int ret;
-
-       ASSERT_RTNL();
-       ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
-                           name, ieee80211_if_setup);
-       if (!ndev)
-               return -ENOMEM;
+       sdata->fragment_next = 0;
 
-       ndev->needed_headroom = local->tx_headroom +
-                               4*6 /* four MAC addresses */
-                               + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
-                               + 6 /* mesh */
-                               + 8 /* rfc1042/bridge tunnel */
-                               - ETH_HLEN /* ethernet hard_header_len */
-                               + IEEE80211_ENCRYPT_HEADROOM;
-       ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
-
-       ret = dev_alloc_name(ndev, ndev->name);
-       if (ret < 0)
-               goto fail;
-
-       memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
-       ndev->base_addr = dev->base_addr;
-       ndev->irq = dev->irq;
-       ndev->mem_start = dev->mem_start;
-       ndev->mem_end = dev->mem_end;
-       SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
-
-       sdata = IEEE80211_DEV_TO_SUB_IF(ndev);
-       ndev->ieee80211_ptr = &sdata->wdev;
-       sdata->wdev.wiphy = local->hw.wiphy;
-       sdata->vif.type = IEEE80211_IF_TYPE_AP;
-       sdata->dev = ndev;
-       sdata->local = local;
-       ieee80211_if_sdata_init(sdata);
-
-       ret = register_netdevice(ndev);
-       if (ret)
-               goto fail;
-
-       ieee80211_debugfs_add_netdev(sdata);
-       ieee80211_if_set_type(ndev, type);
+       switch (sdata->vif.type) {
+       case IEEE80211_IF_TYPE_AP:
+               beacon = sdata->u.ap.beacon;
+               rcu_assign_pointer(sdata->u.ap.beacon, NULL);
+               synchronize_rcu();
+               kfree(beacon);
 
-       if (ieee80211_vif_is_mesh(&sdata->vif) &&
-           params && params->mesh_id_len)
-               ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
-                                            params->mesh_id_len,
-                                            params->mesh_id);
+               while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
+                       local->total_ps_buffered--;
+                       dev_kfree_skb(skb);
+               }
 
-       /* we're under RTNL so all this is fine */
-       if (unlikely(local->reg_state == IEEE80211_DEV_UNREGISTERED)) {
-               __ieee80211_if_del(local, sdata);
-               return -ENODEV;
+               break;
+       case IEEE80211_IF_TYPE_MESH_POINT:
+               /* Allow compiler to elide mesh_rmc_free call. */
+               if (ieee80211_vif_is_mesh(&sdata->vif))
+                       mesh_rmc_free(dev);
+               /* fall through */
+       case IEEE80211_IF_TYPE_STA:
+       case IEEE80211_IF_TYPE_IBSS:
+               kfree(sdata->u.sta.extra_ie);
+               kfree(sdata->u.sta.assocreq_ies);
+               kfree(sdata->u.sta.assocresp_ies);
+               kfree_skb(sdata->u.sta.probe_resp);
+               break;
+       case IEEE80211_IF_TYPE_WDS:
+       case IEEE80211_IF_TYPE_VLAN:
+       case IEEE80211_IF_TYPE_MNTR:
+               break;
+       case IEEE80211_IF_TYPE_INVALID:
+               BUG();
+               break;
        }
-       list_add_tail_rcu(&sdata->list, &local->interfaces);
 
-       if (new_dev)
-               *new_dev = ndev;
-
-       return 0;
-
-fail:
-       free_netdev(ndev);
-       return ret;
+       flushed = sta_info_flush(local, sdata);
+       WARN_ON(flushed);
 }
 
-void ieee80211_if_set_type(struct net_device *dev, int type)
+/*
+ * Helper function to initialise an interface to a specific type.
+ */
+static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata,
+                                 enum ieee80211_if_types type)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       int oldtype = sdata->vif.type;
-
-       /*
-        * We need to call this function on the master interface
-        * which already has a hard_start_xmit routine assigned
-        * which must not be changed.
-        */
-       if (dev != sdata->local->mdev)
-               dev->hard_start_xmit = ieee80211_subif_start_xmit;
+       struct ieee80211_if_sta *ifsta;
 
-       /*
-        * Called even when register_netdevice fails, it would
-        * oops if assigned before initialising the rest.
-        */
-       dev->uninit = ieee80211_if_reinit;
+       /* clear type-dependent union */
+       memset(&sdata->u, 0, sizeof(sdata->u));
 
-       /* most have no BSS pointer */
-       sdata->bss = NULL;
+       /* and set some type-dependent values */
        sdata->vif.type = type;
 
-       sdata->basic_rates = 0;
+       /* only monitor differs */
+       sdata->dev->type = ARPHRD_ETHER;
 
        switch (type) {
-       case IEEE80211_IF_TYPE_WDS:
-               /* nothing special */
-               break;
-       case IEEE80211_IF_TYPE_VLAN:
-               sdata->u.vlan.ap = NULL;
-               break;
        case IEEE80211_IF_TYPE_AP:
-               sdata->u.ap.force_unicast_rateidx = -1;
-               sdata->u.ap.max_ratectrl_rateidx = -1;
                skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
-               sdata->bss = &sdata->u.ap;
                INIT_LIST_HEAD(&sdata->u.ap.vlans);
                break;
        case IEEE80211_IF_TYPE_MESH_POINT:
        case IEEE80211_IF_TYPE_STA:
-       case IEEE80211_IF_TYPE_IBSS: {
-               struct ieee80211_sub_if_data *msdata;
-               struct ieee80211_if_sta *ifsta;
-
+       case IEEE80211_IF_TYPE_IBSS:
                ifsta = &sdata->u.sta;
                INIT_WORK(&ifsta->work, ieee80211_sta_work);
                setup_timer(&ifsta->timer, ieee80211_sta_timer,
@@ -171,153 +118,152 @@ void ieee80211_if_set_type(struct net_device *dev, int type)
                if (ieee80211_num_regular_queues(&sdata->local->hw) >= 4)
                        ifsta->flags |= IEEE80211_STA_WMM_ENABLED;
 
-               msdata = IEEE80211_DEV_TO_SUB_IF(sdata->local->mdev);
-               sdata->bss = &msdata->u.ap;
-
                if (ieee80211_vif_is_mesh(&sdata->vif))
                        ieee80211_mesh_init_sdata(sdata);
                break;
-       }
        case IEEE80211_IF_TYPE_MNTR:
-               dev->type = ARPHRD_IEEE80211_RADIOTAP;
-               dev->hard_start_xmit = ieee80211_monitor_start_xmit;
+               sdata->dev->type = ARPHRD_IEEE80211_RADIOTAP;
+               sdata->dev->hard_start_xmit = ieee80211_monitor_start_xmit;
                sdata->u.mntr_flags = MONITOR_FLAG_CONTROL |
                                      MONITOR_FLAG_OTHER_BSS;
                break;
+       case IEEE80211_IF_TYPE_WDS:
+       case IEEE80211_IF_TYPE_VLAN:
+               break;
        case IEEE80211_IF_TYPE_INVALID:
                BUG();
                break;
        }
-       ieee80211_debugfs_change_if_type(sdata, oldtype);
+
+       ieee80211_debugfs_add_netdev(sdata);
 }
 
-/* Must be called with rtnl lock held. */
-void ieee80211_if_reinit(struct net_device *dev)
+int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata,
+                            enum ieee80211_if_types type)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct sk_buff *skb;
-       int flushed;
+       ASSERT_RTNL();
+
+       if (type == sdata->vif.type)
+               return 0;
+
+       /*
+        * We could, here, on changes between IBSS/STA/MESH modes,
+        * invoke an MLME function instead that disassociates etc.
+        * and goes into the requested mode.
+        */
+
+       if (netif_running(sdata->dev))
+               return -EBUSY;
+
+       /* Purge and reset type-dependent state. */
+       ieee80211_teardown_sdata(sdata->dev);
+       ieee80211_setup_sdata(sdata, type);
+
+       /* reset some values that shouldn't be kept across type changes */
+       sdata->basic_rates = 0;
+       sdata->drop_unencrypted = 0;
+
+       return 0;
+}
+
+int ieee80211_if_add(struct ieee80211_local *local, const char *name,
+                    struct net_device **new_dev, enum ieee80211_if_types type,
+                    struct vif_params *params)
+{
+       struct net_device *ndev;
+       struct ieee80211_sub_if_data *sdata = NULL;
+       int ret, i;
 
        ASSERT_RTNL();
 
-       ieee80211_free_keys(sdata);
+       ndev = alloc_netdev(sizeof(*sdata) + local->hw.vif_data_size,
+                           name, ieee80211_if_setup);
+       if (!ndev)
+               return -ENOMEM;
 
-       ieee80211_if_sdata_deinit(sdata);
+       ndev->needed_headroom = local->tx_headroom +
+                               4*6 /* four MAC addresses */
+                               + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */
+                               + 6 /* mesh */
+                               + 8 /* rfc1042/bridge tunnel */
+                               - ETH_HLEN /* ethernet hard_header_len */
+                               + IEEE80211_ENCRYPT_HEADROOM;
+       ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM;
 
-       /* Need to handle mesh specially to allow eliding the function call */
-       if (ieee80211_vif_is_mesh(&sdata->vif))
-               mesh_rmc_free(dev);
+       ret = dev_alloc_name(ndev, ndev->name);
+       if (ret < 0)
+               goto fail;
 
-       switch (sdata->vif.type) {
-       case IEEE80211_IF_TYPE_INVALID:
-               /* cannot happen */
-               WARN_ON(1);
-               break;
-       case IEEE80211_IF_TYPE_AP: {
-               /* Remove all virtual interfaces that use this BSS
-                * as their sdata->bss */
-               struct ieee80211_sub_if_data *tsdata, *n;
-               struct beacon_data *beacon;
-
-               list_for_each_entry_safe(tsdata, n, &local->interfaces, list) {
-                       if (tsdata != sdata && tsdata->bss == &sdata->u.ap) {
-                               printk(KERN_DEBUG "%s: removing virtual "
-                                      "interface %s because its BSS interface"
-                                      " is being removed\n",
-                                      sdata->dev->name, tsdata->dev->name);
-                               list_del_rcu(&tsdata->list);
-                               /*
-                                * We have lots of time and can afford
-                                * to sync for each interface
-                                */
-                               synchronize_rcu();
-                               __ieee80211_if_del(local, tsdata);
-                       }
-               }
+       memcpy(ndev->dev_addr, local->hw.wiphy->perm_addr, ETH_ALEN);
+       SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy));
 
-               beacon = sdata->u.ap.beacon;
-               rcu_assign_pointer(sdata->u.ap.beacon, NULL);
-               synchronize_rcu();
-               kfree(beacon);
+       /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */
+       sdata = netdev_priv(ndev);
+       ndev->ieee80211_ptr = &sdata->wdev;
 
-               while ((skb = skb_dequeue(&sdata->u.ap.ps_bc_buf))) {
-                       local->total_ps_buffered--;
-                       dev_kfree_skb(skb);
-               }
+       /* initialise type-independent data */
+       sdata->wdev.wiphy = local->hw.wiphy;
+       sdata->local = local;
+       sdata->dev = ndev;
 
-               break;
-       }
-       case IEEE80211_IF_TYPE_WDS:
-               /* nothing to do */
-               break;
-       case IEEE80211_IF_TYPE_MESH_POINT:
-       case IEEE80211_IF_TYPE_STA:
-       case IEEE80211_IF_TYPE_IBSS:
-               kfree(sdata->u.sta.extra_ie);
-               sdata->u.sta.extra_ie = NULL;
-               kfree(sdata->u.sta.assocreq_ies);
-               sdata->u.sta.assocreq_ies = NULL;
-               kfree(sdata->u.sta.assocresp_ies);
-               sdata->u.sta.assocresp_ies = NULL;
-               if (sdata->u.sta.probe_resp) {
-                       dev_kfree_skb(sdata->u.sta.probe_resp);
-                       sdata->u.sta.probe_resp = NULL;
-               }
+       for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++)
+               skb_queue_head_init(&sdata->fragments[i].skb_list);
 
-               break;
-       case IEEE80211_IF_TYPE_MNTR:
-               dev->type = ARPHRD_ETHER;
-               break;
-       case IEEE80211_IF_TYPE_VLAN:
-               sdata->u.vlan.ap = NULL;
-               break;
-       }
+       INIT_LIST_HEAD(&sdata->key_list);
 
-       flushed = sta_info_flush(local, sdata);
-       WARN_ON(flushed);
+       sdata->force_unicast_rateidx = -1;
+       sdata->max_ratectrl_rateidx = -1;
 
-       memset(&sdata->u, 0, sizeof(sdata->u));
-       ieee80211_if_sdata_init(sdata);
-}
+       /* setup type-dependent data */
+       ieee80211_setup_sdata(sdata, type);
 
-/* Must be called with rtnl lock held. */
-void __ieee80211_if_del(struct ieee80211_local *local,
-                       struct ieee80211_sub_if_data *sdata)
-{
-       struct net_device *dev = sdata->dev;
+       ret = register_netdevice(ndev);
+       if (ret)
+               goto fail;
 
-       ieee80211_debugfs_remove_netdev(sdata);
-       unregister_netdevice(dev);
-       /* Except master interface, the net_device will be freed by
-        * net_device->destructor (i. e. ieee80211_if_free). */
+       ndev->uninit = ieee80211_teardown_sdata;
+
+       if (ieee80211_vif_is_mesh(&sdata->vif) &&
+           params && params->mesh_id_len)
+               ieee80211_if_sta_set_mesh_id(&sdata->u.sta,
+                                            params->mesh_id_len,
+                                            params->mesh_id);
+
+       list_add_tail_rcu(&sdata->list, &local->interfaces);
+
+       if (new_dev)
+               *new_dev = ndev;
+
+       return 0;
+
+ fail:
+       free_netdev(ndev);
+       return ret;
 }
 
-/* Must be called with rtnl lock held. */
-int ieee80211_if_remove(struct net_device *dev, const char *name, int id)
+void ieee80211_if_remove(struct net_device *dev)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata, *n;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
        ASSERT_RTNL();
 
-       list_for_each_entry_safe(sdata, n, &local->interfaces, list) {
-               if ((sdata->vif.type == id || id == -1) &&
-                   strcmp(name, sdata->dev->name) == 0 &&
-                   sdata->dev != local->mdev) {
-                       list_del_rcu(&sdata->list);
-                       synchronize_rcu();
-                       __ieee80211_if_del(local, sdata);
-                       return 0;
-               }
-       }
-       return -ENODEV;
+       list_del_rcu(&sdata->list);
+       synchronize_rcu();
+       unregister_netdevice(dev);
 }
 
-void ieee80211_if_free(struct net_device *dev)
+/*
+ * Remove all interfaces, may only be called at hardware unregistration
+ * time because it doesn't do RCU-safe list removals.
+ */
+void ieee80211_remove_interfaces(struct ieee80211_local *local)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+       struct ieee80211_sub_if_data *sdata, *tmp;
 
-       ieee80211_if_sdata_deinit(sdata);
-       free_netdev(dev);
+       ASSERT_RTNL();
+
+       list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
+               list_del(&sdata->list);
+               unregister_netdevice(sdata->dev);
+       }
 }
index 1c4d3ba6b8784ef3785c88e4d08f2ff91315a522..36859e7949289c0e01740a1b545204595050cc31 100644 (file)
@@ -105,7 +105,7 @@ static int ieee80211_master_open(struct net_device *dev)
 
        /* we hold the RTNL here so can safely walk the list */
        list_for_each_entry(sdata, &local->interfaces, list) {
-               if (sdata->dev != dev && netif_running(sdata->dev)) {
+               if (netif_running(sdata->dev)) {
                        res = 0;
                        break;
                }
@@ -126,7 +126,7 @@ static int ieee80211_master_stop(struct net_device *dev)
 
        /* we hold the RTNL here so can safely walk the list */
        list_for_each_entry(sdata, &local->interfaces, list)
-               if (sdata->dev != dev && netif_running(sdata->dev))
+               if (netif_running(sdata->dev))
                        dev_close(sdata->dev);
 
        return 0;
@@ -194,7 +194,7 @@ static int ieee80211_open(struct net_device *dev)
        list_for_each_entry(nsdata, &local->interfaces, list) {
                struct net_device *ndev = nsdata->dev;
 
-               if (ndev != dev && ndev != local->mdev && netif_running(ndev)) {
+               if (ndev != dev && netif_running(ndev)) {
                        /*
                         * Allow only a single IBSS interface to be up at any
                         * time. This is restricted because beacon distribution
@@ -209,30 +209,6 @@ static int ieee80211_open(struct net_device *dev)
                            nsdata->vif.type == IEEE80211_IF_TYPE_IBSS)
                                return -EBUSY;
 
-                       /*
-                        * Disallow multiple IBSS/STA mode interfaces.
-                        *
-                        * This is a technical restriction, it is possible although
-                        * most likely not IEEE 802.11 compliant to have multiple
-                        * STAs with just a single hardware (the TSF timer will not
-                        * be adjusted properly.)
-                        *
-                        * However, because mac80211 uses the master device's BSS
-                        * information for each STA/IBSS interface, doing this will
-                        * currently corrupt that BSS information completely, unless,
-                        * a not very useful case, both STAs are associated to the
-                        * same BSS.
-                        *
-                        * To remove this restriction, the BSS information needs to
-                        * be embedded in the STA/IBSS mode sdata instead of using
-                        * the master device's BSS structure.
-                        */
-                       if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-                            sdata->vif.type == IEEE80211_IF_TYPE_IBSS) &&
-                           (nsdata->vif.type == IEEE80211_IF_TYPE_STA ||
-                            nsdata->vif.type == IEEE80211_IF_TYPE_IBSS))
-                               return -EBUSY;
-
                        /*
                         * The remaining checks are only performed for interfaces
                         * with the same MAC address.
@@ -252,7 +228,7 @@ static int ieee80211_open(struct net_device *dev)
                         */
                        if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN &&
                            nsdata->vif.type == IEEE80211_IF_TYPE_AP)
-                               sdata->u.vlan.ap = nsdata;
+                               sdata->bss = &nsdata->u.ap;
                }
        }
 
@@ -262,10 +238,13 @@ static int ieee80211_open(struct net_device *dev)
                        return -ENOLINK;
                break;
        case IEEE80211_IF_TYPE_VLAN:
-               if (!sdata->u.vlan.ap)
+               if (!sdata->bss)
                        return -ENOLINK;
+               list_add(&sdata->u.vlan.list, &sdata->bss->vlans);
                break;
        case IEEE80211_IF_TYPE_AP:
+               sdata->bss = &sdata->u.ap;
+               break;
        case IEEE80211_IF_TYPE_STA:
        case IEEE80211_IF_TYPE_MNTR:
        case IEEE80211_IF_TYPE_IBSS:
@@ -283,14 +262,13 @@ static int ieee80211_open(struct net_device *dev)
                if (local->ops->start)
                        res = local->ops->start(local_to_hw(local));
                if (res)
-                       return res;
+                       goto err_del_bss;
                need_hw_reconfig = 1;
                ieee80211_led_radio(local, local->hw.conf.radio_enabled);
        }
 
        switch (sdata->vif.type) {
        case IEEE80211_IF_TYPE_VLAN:
-               list_add(&sdata->u.vlan.list, &sdata->u.vlan.ap->u.ap.vlans);
                /* no need to tell driver */
                break;
        case IEEE80211_IF_TYPE_MNTR:
@@ -329,7 +307,8 @@ static int ieee80211_open(struct net_device *dev)
                if (res)
                        goto err_stop;
 
-               ieee80211_if_config(dev);
+               if (ieee80211_vif_is_mesh(&sdata->vif))
+                       ieee80211_start_mesh(sdata->dev);
                changed |= ieee80211_reset_erp_info(dev);
                ieee80211_bss_info_change_notify(sdata, changed);
                ieee80211_enable_keys(sdata);
@@ -404,6 +383,10 @@ static int ieee80211_open(struct net_device *dev)
  err_stop:
        if (!local->open_count && local->ops->stop)
                local->ops->stop(local_to_hw(local));
+ err_del_bss:
+       sdata->bss = NULL;
+       if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
+               list_del(&sdata->u.vlan.list);
        return res;
 }
 
@@ -486,7 +469,6 @@ static int ieee80211_stop(struct net_device *dev)
        switch (sdata->vif.type) {
        case IEEE80211_IF_TYPE_VLAN:
                list_del(&sdata->u.vlan.list);
-               sdata->u.vlan.ap = NULL;
                /* no need to tell driver */
                break;
        case IEEE80211_IF_TYPE_MNTR:
@@ -549,6 +531,8 @@ static int ieee80211_stop(struct net_device *dev)
                local->ops->remove_interface(local_to_hw(local), &conf);
        }
 
+       sdata->bss = NULL;
+
        if (local->open_count == 0) {
                if (netif_running(local->mdev))
                        dev_close(local->mdev);
@@ -988,7 +972,6 @@ static const struct header_ops ieee80211_header_ops = {
        .cache_update   = eth_header_cache_update,
 };
 
-/* Must not be called for mdev */
 void ieee80211_if_setup(struct net_device *dev)
 {
        ether_setup(dev);
@@ -998,62 +981,52 @@ void ieee80211_if_setup(struct net_device *dev)
        dev->change_mtu = ieee80211_change_mtu;
        dev->open = ieee80211_open;
        dev->stop = ieee80211_stop;
-       dev->destructor = ieee80211_if_free;
+       dev->destructor = free_netdev;
 }
 
 /* everything else */
 
-static int __ieee80211_if_config(struct net_device *dev,
-                                struct sk_buff *beacon)
+int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed)
 {
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_conf conf;
 
-       if (!local->ops->config_interface || !netif_running(dev))
+       if (WARN_ON(!netif_running(sdata->dev)))
+               return 0;
+
+       if (!local->ops->config_interface)
                return 0;
 
        memset(&conf, 0, sizeof(conf));
-       conf.type = sdata->vif.type;
+       conf.changed = changed;
+
        if (sdata->vif.type == IEEE80211_IF_TYPE_STA ||
            sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
                conf.bssid = sdata->u.sta.bssid;
                conf.ssid = sdata->u.sta.ssid;
                conf.ssid_len = sdata->u.sta.ssid_len;
-       } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
-               conf.beacon = beacon;
-               ieee80211_start_mesh(dev);
        } else if (sdata->vif.type == IEEE80211_IF_TYPE_AP) {
+               conf.bssid = sdata->dev->dev_addr;
                conf.ssid = sdata->u.ap.ssid;
                conf.ssid_len = sdata->u.ap.ssid_len;
-               conf.beacon = beacon;
+       } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
+               u8 zero[ETH_ALEN] = { 0 };
+               conf.bssid = zero;
+               conf.ssid = zero;
+               conf.ssid_len = 0;
+       } else {
+               WARN_ON(1);
+               return -EINVAL;
        }
-       return local->ops->config_interface(local_to_hw(local),
-                                           &sdata->vif, &conf);
-}
 
-int ieee80211_if_config(struct net_device *dev)
-{
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       if (sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT &&
-           (local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
-               return ieee80211_if_config_beacon(dev);
-       return __ieee80211_if_config(dev, NULL);
-}
+       if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID)))
+               return -EINVAL;
 
-int ieee80211_if_config_beacon(struct net_device *dev)
-{
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       struct sk_buff *skb;
+       if (WARN_ON(!conf.ssid && (changed & IEEE80211_IFCC_SSID)))
+               return -EINVAL;
 
-       if (!(local->hw.flags & IEEE80211_HW_HOST_GEN_BEACON_TEMPLATE))
-               return 0;
-       skb = ieee80211_beacon_get(local_to_hw(local), &sdata->vif);
-       if (!skb)
-               return -ENOMEM;
-       return __ieee80211_if_config(dev, skb);
+       return local->ops->config_interface(local_to_hw(local),
+                                           &sdata->vif, &conf);
 }
 
 int ieee80211_hw_config(struct ieee80211_local *local)
@@ -1659,7 +1632,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        int result;
        enum ieee80211_band band;
        struct net_device *mdev;
-       struct ieee80211_sub_if_data *sdata;
+       struct wireless_dev *mwdev;
 
        /*
         * generic code guarantees at least one band,
@@ -1699,8 +1672,7 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        hw->ampdu_queues = 0;
 #endif
 
-       /* for now, mdev needs sub_if_data :/ */
-       mdev = alloc_netdev_mq(sizeof(struct ieee80211_sub_if_data),
+       mdev = alloc_netdev_mq(sizeof(struct wireless_dev),
                               "wmaster%d", ether_setup,
                               ieee80211_num_queues(hw));
        if (!mdev)
@@ -1709,13 +1681,13 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (ieee80211_num_queues(hw) > 1)
                mdev->features |= NETIF_F_MULTI_QUEUE;
 
-       sdata = IEEE80211_DEV_TO_SUB_IF(mdev);
-       mdev->ieee80211_ptr = &sdata->wdev;
-       sdata->wdev.wiphy = local->hw.wiphy;
+       mwdev = netdev_priv(mdev);
+       mdev->ieee80211_ptr = mwdev;
+       mwdev->wiphy = local->hw.wiphy;
 
        local->mdev = mdev;
 
-       ieee80211_rx_bss_list_init(mdev);
+       ieee80211_rx_bss_list_init(local);
 
        mdev->hard_start_xmit = ieee80211_master_start_xmit;
        mdev->open = ieee80211_master_open;
@@ -1724,16 +1696,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        mdev->header_ops = &ieee80211_header_ops;
        mdev->set_multicast_list = ieee80211_master_set_multicast_list;
 
-       sdata->vif.type = IEEE80211_IF_TYPE_AP;
-       sdata->dev = mdev;
-       sdata->local = local;
-       sdata->u.ap.force_unicast_rateidx = -1;
-       sdata->u.ap.max_ratectrl_rateidx = -1;
-       ieee80211_if_sdata_init(sdata);
-
-       /* no RCU needed since we're still during init phase */
-       list_add_tail(&sdata->list, &local->interfaces);
-
        name = wiphy_dev(local->hw.wiphy)->driver->name;
        local->hw.workqueue = create_freezeable_workqueue(name);
        if (!local->hw.workqueue) {
@@ -1779,9 +1741,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        if (result < 0)
                goto fail_dev;
 
-       ieee80211_debugfs_add_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
-       ieee80211_if_set_type(local->mdev, IEEE80211_IF_TYPE_AP);
-
        result = ieee80211_init_rate_ctrl_alg(local,
                                              hw->rate_control_algorithm);
        if (result < 0) {
@@ -1801,13 +1760,12 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        ieee80211_install_qdisc(local->mdev);
 
        /* add one default STA interface */
-       result = ieee80211_if_add(local->mdev, "wlan%d", NULL,
+       result = ieee80211_if_add(local, "wlan%d", NULL,
                                  IEEE80211_IF_TYPE_STA, NULL);
        if (result)
                printk(KERN_WARNING "%s: Failed to add default virtual iface\n",
                       wiphy_name(local->hw.wiphy));
 
-       local->reg_state = IEEE80211_DEV_REGISTERED;
        rtnl_unlock();
 
        ieee80211_led_init(local);
@@ -1817,7 +1775,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 fail_wep:
        rate_control_deinitialize(local);
 fail_rate:
-       ieee80211_debugfs_remove_netdev(IEEE80211_DEV_TO_SUB_IF(local->mdev));
        unregister_netdevice(local->mdev);
        local->mdev = NULL;
 fail_dev:
@@ -1827,10 +1784,8 @@ fail_sta_info:
        debugfs_hw_del(local);
        destroy_workqueue(local->hw.workqueue);
 fail_workqueue:
-       if (local->mdev != NULL) {
-               ieee80211_if_free(local->mdev);
-               local->mdev = NULL;
-       }
+       if (local->mdev)
+               free_netdev(local->mdev);
 fail_mdev_alloc:
        wiphy_unregister(local->hw.wiphy);
        return result;
@@ -1840,42 +1795,27 @@ EXPORT_SYMBOL(ieee80211_register_hw);
 void ieee80211_unregister_hw(struct ieee80211_hw *hw)
 {
        struct ieee80211_local *local = hw_to_local(hw);
-       struct ieee80211_sub_if_data *sdata, *tmp;
 
        tasklet_kill(&local->tx_pending_tasklet);
        tasklet_kill(&local->tasklet);
 
        rtnl_lock();
 
-       BUG_ON(local->reg_state != IEEE80211_DEV_REGISTERED);
-
-       local->reg_state = IEEE80211_DEV_UNREGISTERED;
-
        /*
         * At this point, interface list manipulations are fine
         * because the driver cannot be handing us frames any
         * more and the tasklet is killed.
         */
 
-       /*
-        * First, we remove all non-master interfaces. Do this because they
-        * may have bss pointer dependency on the master, and when we free
-        * the master these would be freed as well, breaking our list
-        * iteration completely.
-        */
-       list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
-               if (sdata->dev == local->mdev)
-                       continue;
-               list_del(&sdata->list);
-               __ieee80211_if_del(local, sdata);
-       }
+       /* First, we remove all virtual interfaces. */
+       ieee80211_remove_interfaces(local);
 
        /* then, finally, remove the master interface */
-       __ieee80211_if_del(local, IEEE80211_DEV_TO_SUB_IF(local->mdev));
+       unregister_netdevice(local->mdev);
 
        rtnl_unlock();
 
-       ieee80211_rx_bss_list_deinit(local->mdev);
+       ieee80211_rx_bss_list_deinit(local);
        ieee80211_clear_tx_pending(local);
        sta_info_stop(local);
        rate_control_deinitialize(local);
@@ -1892,8 +1832,7 @@ void ieee80211_unregister_hw(struct ieee80211_hw *hw)
        wiphy_unregister(local->hw.wiphy);
        ieee80211_wep_free(local);
        ieee80211_led_exit(local);
-       ieee80211_if_free(local->mdev);
-       local->mdev = NULL;
+       free_netdev(local->mdev);
 }
 EXPORT_SYMBOL(ieee80211_unregister_hw);
 
index dbc8cf454bc038af959198b70622a4259ce2618e..8f51375317dd5e94cdb776d047032dbb014d469f 100644 (file)
@@ -78,7 +78,7 @@ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
 static struct ieee80211_sta_bss *
 ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int freq,
                     u8 *ssid, u8 ssid_len);
-static void ieee80211_rx_bss_put(struct net_device *dev,
+static void ieee80211_rx_bss_put(struct ieee80211_local *local,
                                 struct ieee80211_sta_bss *bss);
 static int ieee80211_sta_find_ibss(struct net_device *dev,
                                   struct ieee80211_if_sta *ifsta);
@@ -345,7 +345,7 @@ static void ieee80211_sta_wmm_params(struct net_device *dev,
                params.aifs = pos[0] & 0x0f;
                params.cw_max = ecw2cw((pos[1] & 0xf0) >> 4);
                params.cw_min = ecw2cw(pos[1] & 0x0f);
-               params.txop = pos[2] | (pos[3] << 8);
+               params.txop = get_unaligned_le16(pos + 2);
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
                printk(KERN_DEBUG "%s: WMM queue=%d aci=%d acm=%d aifs=%d "
                       "cWmin=%d cWmax=%d txop=%d\n",
@@ -554,7 +554,7 @@ static void ieee80211_set_associated(struct net_device *dev,
 
                        changed |= ieee80211_handle_bss_capability(sdata, bss);
 
-                       ieee80211_rx_bss_put(dev, bss);
+                       ieee80211_rx_bss_put(local, bss);
                }
 
                if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) {
@@ -760,7 +760,7 @@ static void ieee80211_send_assoc(struct net_device *dev,
                    (local->hw.flags & IEEE80211_HW_SPECTRUM_MGMT))
                        capab |= WLAN_CAPABILITY_SPECTRUM_MGMT;
 
-               ieee80211_rx_bss_put(dev, bss);
+               ieee80211_rx_bss_put(local, bss);
        } else {
                rates = ~0;
                rates_len = sband->n_bitrates;
@@ -992,7 +992,7 @@ static int ieee80211_privacy_mismatch(struct net_device *dev,
        wep_privacy = !!ieee80211_sta_wep_configured(dev);
        privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
 
-       ieee80211_rx_bss_put(dev, bss);
+       ieee80211_rx_bss_put(local, bss);
 
        if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
                return 0;
@@ -2094,7 +2094,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                        sta->last_signal = bss->signal;
                        sta->last_qual = bss->qual;
                        sta->last_noise = bss->noise;
-                       ieee80211_rx_bss_put(dev, bss);
+                       ieee80211_rx_bss_put(local, bss);
                }
 
                err = sta_info_insert(sta);
@@ -2212,10 +2212,9 @@ static void __ieee80211_rx_bss_hash_add(struct net_device *dev,
 
 
 /* Caller must hold local->sta_bss_lock */
-static void __ieee80211_rx_bss_hash_del(struct net_device *dev,
+static void __ieee80211_rx_bss_hash_del(struct ieee80211_local *local,
                                        struct ieee80211_sta_bss *bss)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sta_bss *b, *prev = NULL;
        b = local->sta_bss_hash[STA_HASH(bss->bssid)];
        while (b) {
@@ -2367,39 +2366,35 @@ static void ieee80211_rx_bss_free(struct ieee80211_sta_bss *bss)
 }
 
 
-static void ieee80211_rx_bss_put(struct net_device *dev,
+static void ieee80211_rx_bss_put(struct ieee80211_local *local,
                                 struct ieee80211_sta_bss *bss)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
-
        local_bh_disable();
        if (!atomic_dec_and_lock(&bss->users, &local->sta_bss_lock)) {
                local_bh_enable();
                return;
        }
 
-       __ieee80211_rx_bss_hash_del(dev, bss);
+       __ieee80211_rx_bss_hash_del(local, bss);
        list_del(&bss->list);
        spin_unlock_bh(&local->sta_bss_lock);
        ieee80211_rx_bss_free(bss);
 }
 
 
-void ieee80211_rx_bss_list_init(struct net_device *dev)
+void ieee80211_rx_bss_list_init(struct ieee80211_local *local)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        spin_lock_init(&local->sta_bss_lock);
        INIT_LIST_HEAD(&local->sta_bss_list);
 }
 
 
-void ieee80211_rx_bss_list_deinit(struct net_device *dev)
+void ieee80211_rx_bss_list_deinit(struct ieee80211_local *local)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
        struct ieee80211_sta_bss *bss, *tmp;
 
        list_for_each_entry_safe(bss, tmp, &local->sta_bss_list, list)
-               ieee80211_rx_bss_put(dev, bss);
+               ieee80211_rx_bss_put(local, bss);
 }
 
 
@@ -2411,8 +2406,6 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
        int res, rates, i, j;
        struct sk_buff *skb;
        struct ieee80211_mgmt *mgmt;
-       struct ieee80211_tx_info *control;
-       struct rate_selection ratesel;
        u8 *pos;
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_supported_band *sband;
@@ -2430,7 +2423,7 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
                local->ops->reset_tsf(local_to_hw(local));
        }
        memcpy(ifsta->bssid, bss->bssid, ETH_ALEN);
-       res = ieee80211_if_config(dev);
+       res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
        if (res)
                return res;
 
@@ -2444,19 +2437,16 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
        if (res)
                return res;
 
-       /* Set beacon template */
+       /* Build IBSS probe response */
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400);
-       do {
-               if (!skb)
-                       break;
-
+       if (skb) {
                skb_reserve(skb, local->hw.extra_tx_headroom);
 
                mgmt = (struct ieee80211_mgmt *)
                        skb_put(skb, 24 + sizeof(mgmt->u.beacon));
                memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon));
                mgmt->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-                                                  IEEE80211_STYPE_BEACON);
+                                                  IEEE80211_STYPE_PROBE_RESP);
                memset(mgmt->da, 0xff, ETH_ALEN);
                memcpy(mgmt->sa, dev->dev_addr, ETH_ALEN);
                memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN);
@@ -2500,61 +2490,22 @@ static int ieee80211_sta_join_ibss(struct net_device *dev,
                        memcpy(pos, &bss->supp_rates[8], rates);
                }
 
-               control = IEEE80211_SKB_CB(skb);
-
-               rate_control_get_rate(dev, sband, skb, &ratesel);
-               if (ratesel.rate_idx < 0) {
-                       printk(KERN_DEBUG "%s: Failed to determine TX rate "
-                              "for IBSS beacon\n", dev->name);
-                       break;
-               }
-               control->control.vif = &sdata->vif;
-               control->tx_rate_idx = ratesel.rate_idx;
-               if (sdata->bss_conf.use_short_preamble &&
-                   sband->bitrates[ratesel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
-                       control->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
-               control->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-               control->flags |= IEEE80211_TX_CTL_NO_ACK;
-               control->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
-               control->control.retry_limit = 1;
-
-               ifsta->probe_resp = skb_copy(skb, GFP_ATOMIC);
-               if (ifsta->probe_resp) {
-                       mgmt = (struct ieee80211_mgmt *)
-                               ifsta->probe_resp->data;
-                       mgmt->frame_control =
-                               IEEE80211_FC(IEEE80211_FTYPE_MGMT,
-                                            IEEE80211_STYPE_PROBE_RESP);
-               } else {
-                       printk(KERN_DEBUG "%s: Could not allocate ProbeResp "
-                              "template for IBSS\n", dev->name);
-               }
+               ifsta->probe_resp = skb;
 
-               if (local->ops->beacon_update &&
-                   local->ops->beacon_update(local_to_hw(local), skb) == 0) {
-                       printk(KERN_DEBUG "%s: Configured IBSS beacon "
-                              "template\n", dev->name);
-                       skb = NULL;
-               }
-
-               rates = 0;
-               sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-               for (i = 0; i < bss->supp_rates_len; i++) {
-                       int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
-                       for (j = 0; j < sband->n_bitrates; j++)
-                               if (sband->bitrates[j].bitrate == bitrate)
-                                       rates |= BIT(j);
-               }
-               ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
-
-               ieee80211_sta_def_wmm_params(dev, bss, 1);
-       } while (0);
+               ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
+       }
 
-       if (skb) {
-               printk(KERN_DEBUG "%s: Failed to configure IBSS beacon "
-                      "template\n", dev->name);
-               dev_kfree_skb(skb);
+       rates = 0;
+       sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+       for (i = 0; i < bss->supp_rates_len; i++) {
+               int bitrate = (bss->supp_rates[i] & 0x7f) * 5;
+               for (j = 0; j < sband->n_bitrates; j++)
+                       if (sband->bitrates[j].bitrate == bitrate)
+                               rates |= BIT(j);
        }
+       ifsta->supp_rates_bits[local->hw.conf.channel->band] = rates;
+
+       ieee80211_sta_def_wmm_params(dev, bss, 1);
 
        ifsta->state = IEEE80211_IBSS_JOINED;
        mod_timer(&ifsta->timer, jiffies + IEEE80211_IBSS_MERGE_INTERVAL);
@@ -2775,7 +2726,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
         */
        if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
            bss->probe_resp && beacon) {
-               ieee80211_rx_bss_put(dev, bss);
+               ieee80211_rx_bss_put(local, bss);
                return;
        }
 
@@ -2918,7 +2869,7 @@ static void ieee80211_rx_bss_info(struct net_device *dev,
                }
        }
 
-       ieee80211_rx_bss_put(dev, bss);
+       ieee80211_rx_bss_put(local, bss);
 }
 
 
@@ -3338,7 +3289,7 @@ static void ieee80211_mesh_housekeeping(struct net_device *dev,
 
        free_plinks = mesh_plink_availables(sdata);
        if (free_plinks != sdata->u.sta.accepting_plinks)
-               ieee80211_if_config_beacon(dev);
+               ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON);
 
        mod_timer(&ifsta->timer, jiffies +
                        IEEE80211_MESH_HOUSEKEEPING_INTERVAL);
@@ -3578,7 +3529,7 @@ static int ieee80211_sta_config_auth(struct net_device *dev,
                                               selected->ssid_len);
                ieee80211_sta_set_bssid(dev, selected->bssid);
                ieee80211_sta_def_wmm_params(dev, selected, 0);
-               ieee80211_rx_bss_put(dev, selected);
+               ieee80211_rx_bss_put(local, selected);
                ifsta->state = IEEE80211_AUTHENTICATE;
                ieee80211_sta_reset_auth(dev, ifsta);
                return 0;
@@ -3655,7 +3606,7 @@ static int ieee80211_sta_create_ibss(struct net_device *dev,
        }
 
        ret = ieee80211_sta_join_ibss(dev, ifsta, bss);
-       ieee80211_rx_bss_put(dev, bss);
+       ieee80211_rx_bss_put(local, bss);
        return ret;
 }
 
@@ -3711,7 +3662,7 @@ static int ieee80211_sta_find_ibss(struct net_device *dev,
                       " based on configured SSID\n",
                       dev->name, print_mac(mac, bssid));
                ret = ieee80211_sta_join_ibss(dev, ifsta, bss);
-               ieee80211_rx_bss_put(dev, bss);
+               ieee80211_rx_bss_put(local, bss);
                return ret;
        }
 #ifdef CONFIG_MAC80211_IBSS_DEBUG
@@ -3762,28 +3713,45 @@ int ieee80211_sta_set_ssid(struct net_device *dev, char *ssid, size_t len)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_if_sta *ifsta;
+       int res;
 
        if (len > IEEE80211_MAX_SSID_LEN)
                return -EINVAL;
 
        ifsta = &sdata->u.sta;
 
-       if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0)
+       if (ifsta->ssid_len != len || memcmp(ifsta->ssid, ssid, len) != 0) {
+               memset(ifsta->ssid, 0, sizeof(ifsta->ssid));
+               memcpy(ifsta->ssid, ssid, len);
+               ifsta->ssid_len = len;
                ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET;
-       memcpy(ifsta->ssid, ssid, len);
-       memset(ifsta->ssid + len, 0, IEEE80211_MAX_SSID_LEN - len);
-       ifsta->ssid_len = len;
+
+               res = 0;
+               /*
+                * Hack! MLME code needs to be cleaned up to have different
+                * entry points for configuration and internal selection change
+                */
+               if (netif_running(sdata->dev))
+                       res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
+               if (res) {
+                       printk(KERN_DEBUG "%s: Failed to config new SSID to "
+                              "the low-level driver\n", dev->name);
+                       return res;
+               }
+       }
 
        if (len)
                ifsta->flags |= IEEE80211_STA_SSID_SET;
        else
                ifsta->flags &= ~IEEE80211_STA_SSID_SET;
+
        if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS &&
            !(ifsta->flags & IEEE80211_STA_BSSID_SET)) {
                ifsta->ibss_join_req = jiffies;
                ifsta->state = IEEE80211_IBSS_SEARCH;
                return ieee80211_sta_find_ibss(dev, ifsta);
        }
+
        return 0;
 }
 
@@ -3809,7 +3777,12 @@ int ieee80211_sta_set_bssid(struct net_device *dev, u8 *bssid)
 
        if (memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) {
                memcpy(ifsta->bssid, bssid, ETH_ALEN);
-               res = ieee80211_if_config(dev);
+               res = 0;
+               /*
+                * Hack! See also ieee80211_sta_set_ssid.
+                */
+               if (netif_running(sdata->dev))
+                       res = ieee80211_if_config(sdata, IEEE80211_IFCC_BSSID);
                if (res) {
                        printk(KERN_DEBUG "%s: Failed to config new BSSID to "
                               "the low-level driver\n", dev->name);
@@ -3907,11 +3880,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw)
 
        rcu_read_lock();
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-
-               /* No need to wake the master device. */
-               if (sdata->dev == local->mdev)
-                       continue;
-
                /* Tell AP we're back */
                if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
                    sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED)
@@ -4077,12 +4045,6 @@ static int ieee80211_sta_start_scan(struct net_device *dev,
 
        rcu_read_lock();
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
-
-               /* Don't stop the master interface, otherwise we can't transmit
-                * probes! */
-               if (sdata->dev == local->mdev)
-                       continue;
-
                netif_stop_queue(sdata->dev);
                if (sdata->vif.type == IEEE80211_IF_TYPE_STA &&
                    (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED))
@@ -4398,7 +4360,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct net_device *dev,
                return NULL;
        }
 
-       if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid))
+       if (compare_ether_addr(bssid, sdata->u.sta.bssid))
                return NULL;
 
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
@@ -4473,12 +4435,10 @@ void ieee80211_notify_mac(struct ieee80211_hw *hw,
        case IEEE80211_NOTIFY_RE_ASSOC:
                rcu_read_lock();
                list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+                       if (sdata->vif.type != IEEE80211_IF_TYPE_STA)
+                               continue;
 
-                       if (sdata->vif.type == IEEE80211_IF_TYPE_STA) {
-                               ieee80211_sta_req_auth(sdata->dev,
-                                                      &sdata->u.sta);
-                       }
-
+                       ieee80211_sta_req_auth(sdata->dev, &sdata->u.sta);
                }
                rcu_read_unlock();
                break;
index 742c5b06cffd0d5cfa47b14617fabbb917788a45..a914ba73ccf56a3d828fa88a851dc44eebfd8fdb 100644 (file)
@@ -259,8 +259,8 @@ static void rate_control_pid_tx_status(void *priv, struct net_device *dev,
 
        /* Don't update the state if we're not controlling the rate. */
        sdata = sta->sdata;
-       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1) {
-               sta->txrate_idx = sdata->bss->max_ratectrl_rateidx;
+       if (sdata->force_unicast_rateidx > -1) {
+               sta->txrate_idx = sdata->max_ratectrl_rateidx;
                goto unlock;
        }
 
@@ -337,8 +337,8 @@ static void rate_control_pid_get_rate(void *priv, struct net_device *dev,
 
        /* If a forced rate is in effect, select it. */
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       if (sdata->bss && sdata->bss->force_unicast_rateidx > -1)
-               sta->txrate_idx = sdata->bss->force_unicast_rateidx;
+       if (sdata->force_unicast_rateidx > -1)
+               sta->txrate_idx = sdata->force_unicast_rateidx;
 
        rateidx = sta->txrate_idx;
 
index fab443d717eb9d2c66c7c1e9d5388bb6982a11e9..6d9ae67c27ca6f48f4e63cc3d36354fab9e21dc6 100644 (file)
@@ -334,13 +334,18 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx)
                else
                        rx->flags &= ~IEEE80211_RX_AMSDU;
        } else {
-               if (unlikely(ieee80211_is_mgmt(hdr->frame_control))) {
-                       /* Separate TID for management frames */
-                       tid = NUM_RX_DATA_QUEUES - 1;
-               } else {
-                       /* no qos control present */
-                       tid = 0; /* 802.1d - Best Effort */
-               }
+               /*
+                * IEEE 802.11-2007, 7.1.3.4.1 ("Sequence Number field"):
+                *
+                *      Sequence numbers for management frames, QoS data
+                *      frames with a broadcast/multicast address in the
+                *      Address 1 field, and all non-QoS data frames sent
+                *      by QoS STAs are assigned using an additional single
+                *      modulo-4096 counter, [...]
+                *
+                * We also use that counter for non-QoS STAs.
+                */
+               tid = NUM_RX_DATA_QUEUES - 1;
        }
 
        rx->queue = tid;
@@ -647,8 +652,7 @@ static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
 
        sdata = sta->sdata;
 
-       if (sdata->bss)
-               atomic_inc(&sdata->bss->num_sta_ps);
+       atomic_inc(&sdata->bss->num_sta_ps);
        set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
        printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
@@ -667,8 +671,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
 
        sdata = sta->sdata;
 
-       if (sdata->bss)
-               atomic_dec(&sdata->bss->num_sta_ps);
+       atomic_dec(&sdata->bss->num_sta_ps);
 
        clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
 
@@ -742,7 +745,9 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
        sta->last_qual = rx->status->qual;
        sta->last_noise = rx->status->noise;
 
-       if (!ieee80211_has_morefrags(hdr->frame_control)) {
+       if (!ieee80211_has_morefrags(hdr->frame_control) &&
+           (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP ||
+            rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) {
                /* Change STA power saving mode only in the end of a frame
                 * exchange sequence */
                if (test_sta_flags(sta, WLAN_STA_PS) &&
@@ -1772,11 +1777,6 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                }
-               if (sdata->dev == sdata->local->mdev &&
-                   !(rx->flags & IEEE80211_RX_IN_SCAN))
-                       /* do not receive anything via
-                        * master device when not scanning */
-                       return 0;
                break;
        case IEEE80211_IF_TYPE_WDS:
                if (bssid || !ieee80211_is_data(hdr->frame_control))
@@ -2046,8 +2046,8 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
 
        tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
 
-       /* null data frames are excluded */
-       if (unlikely(ieee80211_is_nullfunc(hdr->frame_control)))
+       /* qos null data frames are excluded */
+       if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
                goto end_reorder;
 
        /* new un-ordered ampdu frame - process it */
index 47d2c1bbfcaaa1b6b403f5fdfff51b410e540178..f2ba653b9d69525601293b930e838f878db8f05b 100644 (file)
@@ -320,7 +320,9 @@ int sta_info_insert(struct sta_info *sta)
        /* notify driver */
        if (local->ops->sta_notify) {
                if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
-                       sdata = sdata->u.vlan.ap;
+                       sdata = container_of(sdata->bss,
+                                            struct ieee80211_sub_if_data,
+                                            u.ap);
 
                local->ops->sta_notify(local_to_hw(local), &sdata->vif,
                                       STA_NOTIFY_ADD, sta->addr);
@@ -375,8 +377,10 @@ static inline void __bss_tim_clear(struct ieee80211_if_ap *bss, u16 aid)
 static void __sta_info_set_tim_bit(struct ieee80211_if_ap *bss,
                                   struct sta_info *sta)
 {
-       if (bss)
-               __bss_tim_set(bss, sta->aid);
+       BUG_ON(!bss);
+
+       __bss_tim_set(bss, sta->aid);
+
        if (sta->local->ops->set_tim) {
                sta->local->tim_in_locked_section = true;
                sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 1);
@@ -388,6 +392,8 @@ void sta_info_set_tim_bit(struct sta_info *sta)
 {
        unsigned long flags;
 
+       BUG_ON(!sta->sdata->bss);
+
        spin_lock_irqsave(&sta->local->sta_lock, flags);
        __sta_info_set_tim_bit(sta->sdata->bss, sta);
        spin_unlock_irqrestore(&sta->local->sta_lock, flags);
@@ -396,8 +402,10 @@ void sta_info_set_tim_bit(struct sta_info *sta)
 static void __sta_info_clear_tim_bit(struct ieee80211_if_ap *bss,
                                     struct sta_info *sta)
 {
-       if (bss)
-               __bss_tim_clear(bss, sta->aid);
+       BUG_ON(!bss);
+
+       __bss_tim_clear(bss, sta->aid);
+
        if (sta->local->ops->set_tim) {
                sta->local->tim_in_locked_section = true;
                sta->local->ops->set_tim(local_to_hw(sta->local), sta->aid, 0);
@@ -409,6 +417,8 @@ void sta_info_clear_tim_bit(struct sta_info *sta)
 {
        unsigned long flags;
 
+       BUG_ON(!sta->sdata->bss);
+
        spin_lock_irqsave(&sta->local->sta_lock, flags);
        __sta_info_clear_tim_bit(sta->sdata->bss, sta);
        spin_unlock_irqrestore(&sta->local->sta_lock, flags);
@@ -437,8 +447,9 @@ void __sta_info_unlink(struct sta_info **sta)
        list_del(&(*sta)->list);
 
        if (test_and_clear_sta_flags(*sta, WLAN_STA_PS)) {
-               if (sdata->bss)
-                       atomic_dec(&sdata->bss->num_sta_ps);
+               BUG_ON(!sdata->bss);
+
+               atomic_dec(&sdata->bss->num_sta_ps);
                __sta_info_clear_tim_bit(sdata->bss, *sta);
        }
 
@@ -446,7 +457,9 @@ void __sta_info_unlink(struct sta_info **sta)
 
        if (local->ops->sta_notify) {
                if (sdata->vif.type == IEEE80211_IF_TYPE_VLAN)
-                       sdata = sdata->u.vlan.ap;
+                       sdata = container_of(sdata->bss,
+                                            struct ieee80211_sub_if_data,
+                                            u.ap);
 
                local->ops->sta_notify(local_to_hw(local), &sdata->vif,
                                       STA_NOTIFY_REMOVE, (*sta)->addr);
index 94311dcfe043b0752ca584d8eb974b633cdc68c0..109db787ccb754cf8015bd3cc39c950f11b48d04 100644 (file)
@@ -285,6 +285,7 @@ struct sta_info {
        unsigned long tx_fragments;
        int txrate_idx;
        int last_txrate_idx;
+       u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
 #ifdef CONFIG_MAC80211_DEBUG_COUNTERS
        unsigned int wme_tx_queue[NUM_RX_DATA_QUEUES];
 #endif
index 9bd9faac3c3c365848f8bf5d0cd432b32c22d520..0fbadd8b983c821df9de353217e998058565718f 100644 (file)
 
 /* misc utils */
 
-static inline void ieee80211_include_sequence(struct ieee80211_sub_if_data *sdata,
-                                             struct ieee80211_hdr *hdr)
-{
-       /* Set the sequence number for this frame. */
-       hdr->seq_ctrl = cpu_to_le16(sdata->sequence);
-
-       /* Increase the sequence number. */
-       sdata->sequence = (sdata->sequence + 0x10) & IEEE80211_SCTL_SEQ;
-}
-
 #ifdef CONFIG_MAC80211_LOWTX_FRAME_DUMP
 static void ieee80211_dump_frame(const char *ifname, const char *title,
                                 const struct sk_buff *skb)
@@ -274,17 +264,6 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
        return TX_CONTINUE;
 }
 
-static ieee80211_tx_result debug_noinline
-ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
-{
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
-
-       if (ieee80211_hdrlen(hdr->frame_control) >= 24)
-               ieee80211_include_sequence(tx->sdata, hdr);
-
-       return TX_CONTINUE;
-}
-
 /* This function is called whenever the AP is about to exceed the maximum limit
  * of buffered frames for power saving STAs. This situation should not really
  * happen often during normal operation, so dropping the oldest buffered packet
@@ -303,8 +282,7 @@ static void purge_old_ps_buffers(struct ieee80211_local *local)
 
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
                struct ieee80211_if_ap *ap;
-               if (sdata->dev == local->mdev ||
-                   sdata->vif.type != IEEE80211_IF_TYPE_AP)
+               if (sdata->vif.type != IEEE80211_IF_TYPE_AP)
                        continue;
                ap = &sdata->u.ap;
                skb = skb_dequeue(&ap->ps_bc_buf);
@@ -346,8 +324,12 @@ ieee80211_tx_h_multicast_ps_buf(struct ieee80211_tx_data *tx)
         * This is done either by the hardware or us.
         */
 
-       /* not AP/IBSS or ordered frame */
-       if (!tx->sdata->bss || (tx->fc & IEEE80211_FCTL_ORDER))
+       /* powersaving STAs only in AP/VLAN mode */
+       if (!tx->sdata->bss)
+               return TX_CONTINUE;
+
+       /* no buffering for ordered frames */
+       if (tx->fc & IEEE80211_FCTL_ORDER)
                return TX_CONTINUE;
 
        /* no stations in PS mode */
@@ -638,6 +620,49 @@ ieee80211_tx_h_misc(struct ieee80211_tx_data *tx)
        return TX_CONTINUE;
 }
 
+static ieee80211_tx_result debug_noinline
+ieee80211_tx_h_sequence(struct ieee80211_tx_data *tx)
+{
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx->skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data;
+       u16 *seq;
+       u8 *qc;
+       int tid;
+
+       /* only for injected frames */
+       if (unlikely(ieee80211_is_ctl(hdr->frame_control)))
+               return TX_CONTINUE;
+
+       if (ieee80211_hdrlen(hdr->frame_control) < 24)
+               return TX_CONTINUE;
+
+       if (!ieee80211_is_data_qos(hdr->frame_control)) {
+               info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
+               return TX_CONTINUE;
+       }
+
+       /*
+        * This should be true for injected/management frames only, for
+        * management frames we have set the IEEE80211_TX_CTL_ASSIGN_SEQ
+        * above since they are not QoS-data frames.
+        */
+       if (!tx->sta)
+               return TX_CONTINUE;
+
+       /* include per-STA, per-TID sequence counter */
+
+       qc = ieee80211_get_qos_ctl(hdr);
+       tid = *qc & IEEE80211_QOS_CTL_TID_MASK;
+       seq = &tx->sta->tid_seq[tid];
+
+       hdr->seq_ctrl = cpu_to_le16(*seq);
+
+       /* Increase the sequence number. */
+       *seq = (*seq + 0x10) & IEEE80211_SCTL_SEQ;
+
+       return TX_CONTINUE;
+}
+
 static ieee80211_tx_result debug_noinline
 ieee80211_tx_h_fragment(struct ieee80211_tx_data *tx)
 {
@@ -1107,12 +1132,12 @@ static int invoke_tx_handlers(struct ieee80211_tx_data *tx)
                goto txh_done;
 
        CALL_TXH(ieee80211_tx_h_check_assoc)
-       CALL_TXH(ieee80211_tx_h_sequence)
        CALL_TXH(ieee80211_tx_h_ps_buf)
        CALL_TXH(ieee80211_tx_h_select_key)
        CALL_TXH(ieee80211_tx_h_michael_mic_add)
        CALL_TXH(ieee80211_tx_h_rate_ctrl)
        CALL_TXH(ieee80211_tx_h_misc)
+       CALL_TXH(ieee80211_tx_h_sequence)
        CALL_TXH(ieee80211_tx_h_fragment)
        /* handlers after fragment must be aware of tx info fragmentation! */
        CALL_TXH(ieee80211_tx_h_encrypt)
@@ -1785,17 +1810,17 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
                                     struct ieee80211_vif *vif)
 {
        struct ieee80211_local *local = hw_to_local(hw);
-       struct sk_buff *skb;
+       struct sk_buff *skb = NULL;
        struct ieee80211_tx_info *info;
        struct net_device *bdev;
        struct ieee80211_sub_if_data *sdata = NULL;
        struct ieee80211_if_ap *ap = NULL;
+       struct ieee80211_if_sta *ifsta = NULL;
        struct rate_selection rsel;
        struct beacon_data *beacon;
        struct ieee80211_supported_band *sband;
        struct ieee80211_mgmt *mgmt;
        int *num_beacons;
-       bool err = true;
        enum ieee80211_band band = local->hw.conf.channel->band;
        u8 *pos;
 
@@ -1824,9 +1849,6 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
                        memcpy(skb_put(skb, beacon->head_len), beacon->head,
                               beacon->head_len);
 
-                       ieee80211_include_sequence(sdata,
-                                       (struct ieee80211_hdr *)skb->data);
-
                        /*
                         * Not very nice, but we want to allow the driver to call
                         * ieee80211_beacon_get() as a response to the set_tim()
@@ -1849,9 +1871,24 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
                                       beacon->tail, beacon->tail_len);
 
                        num_beacons = &ap->num_beacons;
+               } else
+                       goto out;
+       } else if (sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+               struct ieee80211_hdr *hdr;
+               ifsta = &sdata->u.sta;
 
-                       err = false;
-               }
+               if (!ifsta->probe_resp)
+                       goto out;
+
+               skb = skb_copy(ifsta->probe_resp, GFP_ATOMIC);
+               if (!skb)
+                       goto out;
+
+               hdr = (struct ieee80211_hdr *) skb->data;
+               hdr->frame_control = IEEE80211_FC(IEEE80211_FTYPE_MGMT,
+                                                 IEEE80211_STYPE_BEACON);
+
+               num_beacons = &ifsta->num_beacons;
        } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
                /* headroom, head length, tail length and maximum TIM length */
                skb = dev_alloc_skb(local->tx_headroom + 400);
@@ -1878,17 +1915,8 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
                mesh_mgmt_ies_add(skb, sdata->dev);
 
                num_beacons = &sdata->u.sta.num_beacons;
-
-               err = false;
-       }
-
-       if (err) {
-#ifdef CONFIG_MAC80211_VERBOSE_DEBUG
-               if (net_ratelimit())
-                       printk(KERN_DEBUG "no beacon data avail for %s\n",
-                              bdev->name);
-#endif /* CONFIG_MAC80211_VERBOSE_DEBUG */
-               skb = NULL;
+       } else {
+               WARN_ON(1);
                goto out;
        }
 
@@ -1910,14 +1938,18 @@ struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
 
        info->control.vif = vif;
        info->tx_rate_idx = rsel.rate_idx;
+
+       info->flags |= IEEE80211_TX_CTL_NO_ACK;
+       info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
+       info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+       info->flags |= IEEE80211_TX_CTL_ASSIGN_SEQ;
        if (sdata->bss_conf.use_short_preamble &&
            sband->bitrates[rsel.rate_idx].flags & IEEE80211_RATE_SHORT_PREAMBLE)
                info->flags |= IEEE80211_TX_CTL_SHORT_PREAMBLE;
+
        info->antenna_sel_tx = local->hw.conf.antenna_sel_tx;
-       info->flags |= IEEE80211_TX_CTL_NO_ACK;
-       info->flags |= IEEE80211_TX_CTL_DO_NOT_ENCRYPT;
        info->control.retry_limit = 1;
-       info->flags |= IEEE80211_TX_CTL_CLEAR_PS_FILT;
+
        (*num_beacons)++;
 out:
        rcu_read_unlock();
index ce62b163b82c46d2e8814e29d1f5ce73a2f250c3..89ce4e07bd8402876ed1cbb764191dd61e0534c1 100644 (file)
@@ -428,8 +428,6 @@ void ieee80211_iterate_active_interfaces(
                case IEEE80211_IF_TYPE_MESH_POINT:
                        break;
                }
-               if (sdata->dev == local->mdev)
-                       continue;
                if (netif_running(sdata->dev))
                        iterator(data, sdata->dev->dev_addr,
                                 &sdata->vif);
@@ -463,8 +461,6 @@ void ieee80211_iterate_active_interfaces_atomic(
                case IEEE80211_IF_TYPE_MESH_POINT:
                        break;
                }
-               if (sdata->dev == local->mdev)
-                       continue;
                if (netif_running(sdata->dev))
                        iterator(data, sdata->dev->dev_addr,
                                 &sdata->vif);
index 736c32e340f20c4debeee33e77d84994275ba42b..34fa8ed1e784b4ec727a5d7f651ec5b105b53bb1 100644 (file)
@@ -296,15 +296,7 @@ static int ieee80211_ioctl_siwmode(struct net_device *dev,
                return -EINVAL;
        }
 
-       if (type == sdata->vif.type)
-               return 0;
-       if (netif_running(dev))
-               return -EBUSY;
-
-       ieee80211_if_reinit(dev);
-       ieee80211_if_set_type(dev, type);
-
-       return 0;
+       return ieee80211_if_change_type(sdata, type);
 }
 
 
@@ -452,7 +444,7 @@ static int ieee80211_ioctl_siwessid(struct net_device *dev,
                memset(sdata->u.ap.ssid + len, 0,
                       IEEE80211_MAX_SSID_LEN - len);
                sdata->u.ap.ssid_len = len;
-               return ieee80211_if_config(dev);
+               return ieee80211_if_config(sdata, IEEE80211_IFCC_SSID);
        }
        return -EOPNOTSUPP;
 }
@@ -627,16 +619,14 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev,
        struct ieee80211_supported_band *sband;
 
        sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-       if (!sdata->bss)
-               return -ENODEV;
 
        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
        /* target_rate = -1, rate->fixed = 0 means auto only, so use all rates
         * target_rate = X, rate->fixed = 1 means only rate X
         * target_rate = X, rate->fixed = 0 means all rates <= X */
-       sdata->bss->max_ratectrl_rateidx = -1;
-       sdata->bss->force_unicast_rateidx = -1;
+       sdata->max_ratectrl_rateidx = -1;
+       sdata->force_unicast_rateidx = -1;
        if (rate->value < 0)
                return 0;
 
@@ -645,9 +635,9 @@ static int ieee80211_ioctl_siwrate(struct net_device *dev,
                int this_rate = brate->bitrate;
 
                if (target_rate == this_rate) {
-                       sdata->bss->max_ratectrl_rateidx = i;
+                       sdata->max_ratectrl_rateidx = i;
                        if (rate->fixed)
-                               sdata->bss->force_unicast_rateidx = i;
+                               sdata->force_unicast_rateidx = i;
                        err = 0;
                        break;
                }
@@ -1009,6 +999,45 @@ static int ieee80211_ioctl_giwencode(struct net_device *dev,
        return 0;
 }
 
+static int ieee80211_ioctl_siwpower(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   struct iw_param *wrq,
+                                   char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_conf *conf = &local->hw.conf;
+
+       if (wrq->disabled) {
+               conf->flags &= ~IEEE80211_CONF_PS;
+               return ieee80211_hw_config(local);
+       }
+
+       switch (wrq->flags & IW_POWER_MODE) {
+       case IW_POWER_ON:       /* If not specified */
+       case IW_POWER_MODE:     /* If set all mask */
+       case IW_POWER_ALL_R:    /* If explicitely state all */
+               conf->flags |= IEEE80211_CONF_PS;
+               break;
+       default:                /* Otherwise we don't support it */
+               return -EINVAL;
+       }
+
+       return ieee80211_hw_config(local);
+}
+
+static int ieee80211_ioctl_giwpower(struct net_device *dev,
+                                   struct iw_request_info *info,
+                                   union iwreq_data *wrqu,
+                                   char *extra)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_conf *conf = &local->hw.conf;
+
+       wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS);
+
+       return 0;
+}
+
 static int ieee80211_ioctl_siwauth(struct net_device *dev,
                                   struct iw_request_info *info,
                                   struct iw_param *data, char *extra)
@@ -1211,8 +1240,8 @@ static const iw_handler ieee80211_handler[] =
        (iw_handler) ieee80211_ioctl_giwretry,          /* SIOCGIWRETRY */
        (iw_handler) ieee80211_ioctl_siwencode,         /* SIOCSIWENCODE */
        (iw_handler) ieee80211_ioctl_giwencode,         /* SIOCGIWENCODE */
-       (iw_handler) NULL,                              /* SIOCSIWPOWER */
-       (iw_handler) NULL,                              /* SIOCGIWPOWER */
+       (iw_handler) ieee80211_ioctl_siwpower,          /* SIOCSIWPOWER */
+       (iw_handler) ieee80211_ioctl_giwpower,          /* SIOCGIWPOWER */
        (iw_handler) NULL,                              /* -- hole -- */
        (iw_handler) NULL,                              /* -- hole -- */
        (iw_handler) ieee80211_ioctl_siwgenie,          /* SIOCSIWGENIE */
index 79270903bda6f2bb02553baff2b71137d87bdfd2..ab015c62d5612cd42b558179dee05a00ef3b2218 100644 (file)
@@ -29,3 +29,14 @@ config WIRELESS_EXT
 
          Say N (if you can) unless you know you need wireless
          extensions for external modules.
+
+config WIRELESS_EXT_SYSFS
+       bool "Wireless extensions sysfs files"
+       default y
+       depends on WIRELESS_EXT && SYSFS
+       help
+         This option enables the deprecated wireless statistics
+         files in /sys/class/net/*/wireless/. The same information
+         is available via the ioctls as well.
+
+         Say Y if you have programs using it (we don't know of any).