summaryrefslogtreecommitdiff
path: root/package/mac80211/patches/000-mac80211_update.patch
diff options
context:
space:
mode:
Diffstat (limited to 'package/mac80211/patches/000-mac80211_update.patch')
-rw-r--r--package/mac80211/patches/000-mac80211_update.patch933
1 files changed, 933 insertions, 0 deletions
diff --git a/package/mac80211/patches/000-mac80211_update.patch b/package/mac80211/patches/000-mac80211_update.patch
new file mode 100644
index 0000000..7a1a1e2
--- /dev/null
+++ b/package/mac80211/patches/000-mac80211_update.patch
@@ -0,0 +1,933 @@
+Index: mac80211/include/linux/ieee80211.h
+===================================================================
+--- mac80211.orig/include/linux/ieee80211.h 2007-11-11 15:45:23.153490050 +0100
++++ mac80211/include/linux/ieee80211.h 2007-11-11 15:45:30.417904025 +0100
+@@ -81,18 +81,18 @@
+
+
+ /* miscellaneous IEEE 802.11 constants */
+-#define IEEE80211_MAX_FRAG_THRESHOLD 2346
+-#define IEEE80211_MAX_RTS_THRESHOLD 2347
++#define IEEE80211_MAX_FRAG_THRESHOLD 2352
++#define IEEE80211_MAX_RTS_THRESHOLD 2353
+ #define IEEE80211_MAX_AID 2007
+ #define IEEE80211_MAX_TIM_LEN 251
+-#define IEEE80211_MAX_DATA_LEN 2304
+ /* Maximum size for the MA-UNITDATA primitive, 802.11 standard section
+ 6.2.1.1.2.
+
+- The figure in section 7.1.2 suggests a body size of up to 2312
+- bytes is allowed, which is a bit confusing, I suspect this
+- represents the 2304 bytes of real data, plus a possible 8 bytes of
+- WEP IV and ICV. (this interpretation suggested by Ramiro Barreiro) */
++ 802.11e clarifies the figure in section 7.1.2. The frame body is
++ up to 2304 octets long (maximum MSDU size) plus any crypt overhead. */
++#define IEEE80211_MAX_DATA_LEN 2304
++/* 30 byte 4 addr hdr, 2 byte QoS, 2304 byte MSDU, 12 byte crypt, 4 byte FCS */
++#define IEEE80211_MAX_FRAME_LEN 2352
+
+ #define IEEE80211_MAX_SSID_LEN 32
+
+Index: mac80211/include/linux/nl80211.h
+===================================================================
+--- mac80211.orig/include/linux/nl80211.h 2007-11-11 15:45:23.161490506 +0100
++++ mac80211/include/linux/nl80211.h 2007-11-11 15:45:30.421904255 +0100
+@@ -25,7 +25,7 @@
+ * either a dump request on a %NL80211_ATTR_WIPHY or a specific get
+ * on an %NL80211_ATTR_IFINDEX is supported.
+ * @NL80211_CMD_SET_INTERFACE: Set type of a virtual interface, requires
+- %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE.
++ * %NL80211_ATTR_IFINDEX and %NL80211_ATTR_IFTYPE.
+ * @NL80211_CMD_NEW_INTERFACE: Newly created virtual interface or response
+ * to %NL80211_CMD_GET_INTERFACE. Has %NL80211_ATTR_IFINDEX,
+ * %NL80211_ATTR_WIPHY and %NL80211_ATTR_IFTYPE attributes. Can also
+Index: mac80211/include/net/mac80211.h
+===================================================================
+--- mac80211.orig/include/net/mac80211.h 2007-11-11 15:45:23.169490961 +0100
++++ mac80211/include/net/mac80211.h 2007-11-11 15:45:30.429904707 +0100
+@@ -706,11 +706,16 @@
+ *
+ * @queues: number of available hardware transmit queues for
+ * data packets. WMM/QoS requires at least four.
++ *
++ * @rate_control_algorithm: rate control algorithm for this hardware.
++ * If unset (NULL), the default algorithm will be used. Must be
++ * set before calling ieee80211_register_hw().
+ */
+ struct ieee80211_hw {
+ struct ieee80211_conf conf;
+ struct wiphy *wiphy;
+ struct workqueue_struct *workqueue;
++ const char *rate_control_algorithm;
+ void *priv;
+ u32 flags;
+ unsigned int extra_tx_headroom;
+@@ -936,27 +941,11 @@
+ * and remove_interface calls, i.e. while the interface with the
+ * given local_address is enabled.
+ *
+- * @set_ieee8021x: Enable/disable IEEE 802.1X. This item requests wlan card
+- * to pass unencrypted EAPOL-Key frames even when encryption is
+- * configured. If the wlan card does not require such a configuration,
+- * this function pointer can be set to NULL.
+- *
+- * @set_port_auth: Set port authorization state (IEEE 802.1X PAE) to be
+- * authorized (@authorized=1) or unauthorized (=0). This function can be
+- * used if the wlan hardware or low-level driver implements PAE.
+- * mac80211 will filter frames based on authorization state in any case,
+- * so this function pointer can be NULL if low-level driver does not
+- * require event notification about port state changes.
+- *
+ * @hw_scan: Ask the hardware to service the scan request, no need to start
+ * the scan state machine in stack.
+ *
+ * @get_stats: return low-level statistics
+ *
+- * @set_privacy_invoked: For devices that generate their own beacons and probe
+- * response or association responses this updates the state of privacy_invoked
+- * returns 0 for success or an error number.
+- *
+ * @get_sequence_counter: For devices that have internal sequence counters this
+ * callback allows mac80211 to access the current value of a counter.
+ * This callback seems not well-defined, tell us if you need it.
+@@ -1029,14 +1018,9 @@
+ int (*set_key)(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+ const u8 *local_address, const u8 *address,
+ struct ieee80211_key_conf *key);
+- int (*set_ieee8021x)(struct ieee80211_hw *hw, int use_ieee8021x);
+- int (*set_port_auth)(struct ieee80211_hw *hw, u8 *addr,
+- int authorized);
+ int (*hw_scan)(struct ieee80211_hw *hw, u8 *ssid, size_t len);
+ int (*get_stats)(struct ieee80211_hw *hw,
+ struct ieee80211_low_level_stats *stats);
+- int (*set_privacy_invoked)(struct ieee80211_hw *hw,
+- int privacy_invoked);
+ int (*get_sequence_counter)(struct ieee80211_hw *hw,
+ u8* addr, u8 keyidx, u8 txrx,
+ u32* iv32, u16* iv16);
+Index: mac80211/net/mac80211/aes_ccm.c
+===================================================================
+--- mac80211.orig/net/mac80211/aes_ccm.c 2007-11-11 15:45:23.177491419 +0100
++++ mac80211/net/mac80211/aes_ccm.c 2007-11-11 15:45:30.433904936 +0100
+@@ -7,10 +7,10 @@
+ * published by the Free Software Foundation.
+ */
+
++#include <linux/kernel.h>
+ #include <linux/types.h>
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+-#include <asm/scatterlist.h>
+
+ #include <net/mac80211.h>
+ #include "ieee80211_key.h"
+@@ -63,7 +63,7 @@
+ s_0 = scratch + AES_BLOCK_LEN;
+ e = scratch + 2 * AES_BLOCK_LEN;
+
+- num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
+ last_len = data_len % AES_BLOCK_LEN;
+ aes_ccm_prepare(tfm, b_0, aad, b, s_0, b);
+
+@@ -102,7 +102,7 @@
+ s_0 = scratch + AES_BLOCK_LEN;
+ a = scratch + 2 * AES_BLOCK_LEN;
+
+- num_blocks = (data_len + AES_BLOCK_LEN - 1) / AES_BLOCK_LEN;
++ num_blocks = DIV_ROUND_UP(data_len, AES_BLOCK_LEN);
+ last_len = data_len % AES_BLOCK_LEN;
+ aes_ccm_prepare(tfm, b_0, aad, b, s_0, a);
+
+Index: mac80211/net/mac80211/ieee80211.c
+===================================================================
+--- mac80211.orig/net/mac80211/ieee80211.c 2007-11-11 15:45:23.185491871 +0100
++++ mac80211/net/mac80211/ieee80211.c 2007-11-11 15:45:30.437905164 +0100
+@@ -1061,7 +1061,8 @@
+ 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, NULL);
++ result = ieee80211_init_rate_ctrl_alg(local,
++ hw->rate_control_algorithm);
+ if (result < 0) {
+ printk(KERN_DEBUG "%s: Failed to initialize rate control "
+ "algorithm\n", wiphy_name(local->hw.wiphy));
+@@ -1222,8 +1223,17 @@
+
+ BUILD_BUG_ON(sizeof(struct ieee80211_tx_packet_data) > sizeof(skb->cb));
+
++#ifdef CONFIG_MAC80211_RCSIMPLE
++ ret = ieee80211_rate_control_register(&mac80211_rcsimple);
++ if (ret)
++ return ret;
++#endif
++
+ ret = ieee80211_wme_register();
+ if (ret) {
++#ifdef CONFIG_MAC80211_RCSIMPLE
++ ieee80211_rate_control_unregister(&mac80211_rcsimple);
++#endif
+ printk(KERN_DEBUG "ieee80211_init: failed to "
+ "initialize WME (err=%d)\n", ret);
+ return ret;
+@@ -1237,6 +1247,10 @@
+
+ static void __exit ieee80211_exit(void)
+ {
++#ifdef CONFIG_MAC80211_RCSIMPLE
++ ieee80211_rate_control_unregister(&mac80211_rcsimple);
++#endif
++
+ ieee80211_wme_unregister();
+ ieee80211_debugfs_netdev_exit();
+ }
+Index: mac80211/net/mac80211/ieee80211_i.h
+===================================================================
+--- mac80211.orig/net/mac80211/ieee80211_i.h 2007-11-11 15:45:23.189492100 +0100
++++ mac80211/net/mac80211/ieee80211_i.h 2007-11-11 15:45:30.441905395 +0100
+@@ -232,6 +232,7 @@
+ #define IEEE80211_STA_AUTO_SSID_SEL BIT(10)
+ #define IEEE80211_STA_AUTO_BSSID_SEL BIT(11)
+ #define IEEE80211_STA_AUTO_CHANNEL_SEL BIT(12)
++#define IEEE80211_STA_PRIVACY_INVOKED BIT(13)
+ struct ieee80211_if_sta {
+ enum {
+ IEEE80211_DISABLED, IEEE80211_AUTHENTICATE,
+@@ -261,7 +262,6 @@
+ unsigned long request;
+ struct sk_buff_head skb_queue;
+
+- int key_management_enabled;
+ unsigned long last_probe;
+
+ #define IEEE80211_AUTH_ALG_OPEN BIT(0)
+Index: mac80211/net/mac80211/ieee80211_ioctl.c
+===================================================================
+--- mac80211.orig/net/mac80211/ieee80211_ioctl.c 2007-11-11 15:45:23.197492559 +0100
++++ mac80211/net/mac80211/ieee80211_ioctl.c 2007-11-11 15:45:30.441905395 +0100
+@@ -305,9 +305,12 @@
+ ((chan->chan == channel) || (chan->freq == freq))) {
+ local->oper_channel = chan;
+ local->oper_hw_mode = mode;
+- set++;
++ set = 1;
++ break;
+ }
+ }
++ if (set)
++ break;
+ }
+
+ if (set) {
+@@ -507,10 +510,11 @@
+
+ static int ieee80211_ioctl_siwscan(struct net_device *dev,
+ struct iw_request_info *info,
+- struct iw_point *data, char *extra)
++ union iwreq_data *wrqu, char *extra)
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
++ struct iw_scan_req *req = NULL;
+ u8 *ssid = NULL;
+ size_t ssid_len = 0;
+
+@@ -535,6 +539,14 @@
+ return -EOPNOTSUPP;
+ }
+
++ /* if SSID was specified explicitly then use that */
++ if (wrqu->data.length == sizeof(struct iw_scan_req) &&
++ wrqu->data.flags & IW_SCAN_THIS_ESSID) {
++ req = (struct iw_scan_req *)extra;
++ ssid = req->essid;
++ ssid_len = req->essid_len;
++ }
++
+ return ieee80211_sta_req_scan(dev, ssid, ssid_len);
+ }
+
+@@ -621,22 +633,35 @@
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ bool need_reconfig = 0;
++ u8 new_power_level;
+
+ if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
+ return -EINVAL;
+ if (data->txpower.flags & IW_TXPOW_RANGE)
+ return -EINVAL;
+- if (!data->txpower.fixed)
+- return -EINVAL;
+
+- if (local->hw.conf.power_level != data->txpower.value) {
+- local->hw.conf.power_level = data->txpower.value;
++ if (data->txpower.fixed) {
++ new_power_level = data->txpower.value;
++ } else {
++ /* Automatic power level. Get the px power from the current
++ * channel. */
++ struct ieee80211_channel* chan = local->oper_channel;
++ if (!chan)
++ return -EINVAL;
++
++ new_power_level = chan->power_level;
++ }
++
++ if (local->hw.conf.power_level != new_power_level) {
++ local->hw.conf.power_level = new_power_level;
+ need_reconfig = 1;
+ }
++
+ if (local->hw.conf.radio_enabled != !(data->txpower.disabled)) {
+ local->hw.conf.radio_enabled = !(data->txpower.disabled);
+ need_reconfig = 1;
+ }
++
+ if (need_reconfig) {
+ ieee80211_hw_config(local);
+ /* The return value of hw_config is not of big interest here,
+@@ -904,7 +929,6 @@
+ struct iw_request_info *info,
+ struct iw_param *data, char *extra)
+ {
+- struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ int ret = 0;
+
+@@ -914,18 +938,21 @@
+ case IW_AUTH_CIPHER_GROUP:
+ case IW_AUTH_WPA_ENABLED:
+ case IW_AUTH_RX_UNENCRYPTED_EAPOL:
+- break;
+ case IW_AUTH_KEY_MGMT:
++ break;
++ case IW_AUTH_PRIVACY_INVOKED:
+ if (sdata->type != IEEE80211_IF_TYPE_STA)
+ ret = -EINVAL;
+ else {
++ sdata->u.sta.flags &= ~IEEE80211_STA_PRIVACY_INVOKED;
+ /*
+- * Key management was set by wpa_supplicant,
+- * we only need this to associate to a network
+- * that has privacy enabled regardless of not
+- * having a key.
++ * Privacy invoked by wpa_supplicant, store the
++ * value and allow associating to a protected
++ * network without having a key up front.
+ */
+- sdata->u.sta.key_management_enabled = !!data->value;
++ if (data->value)
++ sdata->u.sta.flags |=
++ IEEE80211_STA_PRIVACY_INVOKED;
+ }
+ break;
+ case IW_AUTH_80211_AUTH_ALG:
+@@ -935,11 +962,6 @@
+ else
+ ret = -EOPNOTSUPP;
+ break;
+- case IW_AUTH_PRIVACY_INVOKED:
+- if (local->ops->set_privacy_invoked)
+- ret = local->ops->set_privacy_invoked(
+- local_to_hw(local), data->value);
+- break;
+ default:
+ ret = -EOPNOTSUPP;
+ break;
+Index: mac80211/net/mac80211/ieee80211_rate.c
+===================================================================
+--- mac80211.orig/net/mac80211/ieee80211_rate.c 2007-11-11 15:45:23.205493011 +0100
++++ mac80211/net/mac80211/ieee80211_rate.c 2007-11-11 15:45:30.441905395 +0100
+@@ -25,13 +25,25 @@
+ {
+ struct rate_control_alg *alg;
+
++ if (!ops->name)
++ return -EINVAL;
++
++ mutex_lock(&rate_ctrl_mutex);
++ list_for_each_entry(alg, &rate_ctrl_algs, list) {
++ if (!strcmp(alg->ops->name, ops->name)) {
++ /* don't register an algorithm twice */
++ WARN_ON(1);
++ return -EALREADY;
++ }
++ }
++
+ alg = kzalloc(sizeof(*alg), GFP_KERNEL);
+ if (alg == NULL) {
++ mutex_unlock(&rate_ctrl_mutex);
+ return -ENOMEM;
+ }
+ alg->ops = ops;
+
+- mutex_lock(&rate_ctrl_mutex);
+ list_add_tail(&alg->list, &rate_ctrl_algs);
+ mutex_unlock(&rate_ctrl_mutex);
+
+@@ -61,9 +73,12 @@
+ struct rate_control_alg *alg;
+ struct rate_control_ops *ops = NULL;
+
++ if (!name)
++ return NULL;
++
+ mutex_lock(&rate_ctrl_mutex);
+ list_for_each_entry(alg, &rate_ctrl_algs, list) {
+- if (!name || !strcmp(alg->ops->name, name))
++ if (!strcmp(alg->ops->name, name))
+ if (try_module_get(alg->ops->module)) {
+ ops = alg->ops;
+ break;
+@@ -80,9 +95,12 @@
+ {
+ struct rate_control_ops *ops;
+
++ if (!name)
++ name = "simple";
++
+ ops = ieee80211_try_rate_control_ops_get(name);
+ if (!ops) {
+- request_module("rc80211_%s", name ? name : "default");
++ request_module("rc80211_%s", name);
+ ops = ieee80211_try_rate_control_ops_get(name);
+ }
+ return ops;
+Index: mac80211/net/mac80211/ieee80211_rate.h
+===================================================================
+--- mac80211.orig/net/mac80211/ieee80211_rate.h 2007-11-11 15:45:23.213493469 +0100
++++ mac80211/net/mac80211/ieee80211_rate.h 2007-11-11 15:45:30.445905621 +0100
+@@ -65,6 +65,9 @@
+ struct kref kref;
+ };
+
++/* default 'simple' algorithm */
++extern struct rate_control_ops mac80211_rcsimple;
++
+ int ieee80211_rate_control_register(struct rate_control_ops *ops);
+ void ieee80211_rate_control_unregister(struct rate_control_ops *ops);
+
+Index: mac80211/net/mac80211/ieee80211_sta.c
+===================================================================
+--- mac80211.orig/net/mac80211/ieee80211_sta.c 2007-11-11 15:45:23.217493699 +0100
++++ mac80211/net/mac80211/ieee80211_sta.c 2007-11-11 15:46:32.885463850 +0100
+@@ -12,7 +12,6 @@
+ */
+
+ /* TODO:
+- * BSS table: use <BSSID,SSID> as the key to support multi-SSID APs
+ * order BSS list by RSSI(?) ("quality of AP")
+ * scan result table filtering (by capability (privacy, IBSS/BSS, WPA/RSN IE,
+ * SSID)
+@@ -61,7 +60,8 @@
+ static void ieee80211_send_probe_req(struct net_device *dev, u8 *dst,
+ u8 *ssid, size_t ssid_len);
+ static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid);
++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
++ u8 *ssid, u8 ssid_len);
+ static void ieee80211_rx_bss_put(struct net_device *dev,
+ struct ieee80211_sta_bss *bss);
+ static int ieee80211_sta_find_ibss(struct net_device *dev,
+@@ -108,14 +108,11 @@
+ u8 wmm_param_len;
+ };
+
+-enum ParseRes { ParseOK = 0, ParseUnknown = 1, ParseFailed = -1 };
+-
+-static enum ParseRes ieee802_11_parse_elems(u8 *start, size_t len,
+- struct ieee802_11_elems *elems)
++static void ieee802_11_parse_elems(u8 *start, size_t len,
++ struct ieee802_11_elems *elems)
+ {
+ size_t left = len;
+ u8 *pos = start;
+- int unknown = 0;
+
+ memset(elems, 0, sizeof(*elems));
+
+@@ -126,15 +123,8 @@
+ elen = *pos++;
+ left -= 2;
+
+- if (elen > left) {
+-#if 0
+- if (net_ratelimit())
+- printk(KERN_DEBUG "IEEE 802.11 element parse "
+- "failed (id=%d elen=%d left=%d)\n",
+- id, elen, left);
+-#endif
+- return ParseFailed;
+- }
++ if (elen > left)
++ return;
+
+ switch (id) {
+ case WLAN_EID_SSID:
+@@ -201,28 +191,15 @@
+ elems->ext_supp_rates_len = elen;
+ break;
+ default:
+-#if 0
+- printk(KERN_DEBUG "IEEE 802.11 element parse ignored "
+- "unknown element (id=%d elen=%d)\n",
+- id, elen);
+-#endif
+- unknown++;
+ break;
+ }
+
+ left -= elen;
+ pos += elen;
+ }
+-
+- /* Do not trigger error if left == 1 as Apple Airport base stations
+- * send AssocResps that are one spurious byte too long. */
+-
+- return unknown ? ParseUnknown : ParseOK;
+ }
+
+
+-
+-
+ static int ecw2cw(int ecw)
+ {
+ int cw = 1;
+@@ -426,7 +403,9 @@
+ if (sdata->type != IEEE80211_IF_TYPE_STA)
+ return;
+
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ local->hw.conf.channel,
++ ifsta->ssid, ifsta->ssid_len);
+ if (bss) {
+ if (bss->has_erp_value)
+ ieee80211_handle_erp_ie(dev, bss->erp_value);
+@@ -571,7 +550,8 @@
+ capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME |
+ WLAN_CAPABILITY_SHORT_PREAMBLE;
+ }
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
++ ifsta->ssid, ifsta->ssid_len);
+ if (bss) {
+ if (bss->capability & WLAN_CAPABILITY_PRIVACY)
+ capab |= WLAN_CAPABILITY_PRIVACY;
+@@ -719,24 +699,30 @@
+ static int ieee80211_privacy_mismatch(struct net_device *dev,
+ struct ieee80211_if_sta *ifsta)
+ {
++ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sta_bss *bss;
+- int res = 0;
++ int bss_privacy;
++ int wep_privacy;
++ int privacy_invoked;
+
+- if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL) ||
+- ifsta->key_management_enabled)
++ if (!ifsta || (ifsta->flags & IEEE80211_STA_MIXED_CELL))
+ return 0;
+
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid, local->hw.conf.channel,
++ ifsta->ssid, ifsta->ssid_len);
+ if (!bss)
+ return 0;
+
+- if (ieee80211_sta_wep_configured(dev) !=
+- !!(bss->capability & WLAN_CAPABILITY_PRIVACY))
+- res = 1;
++ bss_privacy = !!(bss->capability & WLAN_CAPABILITY_PRIVACY);
++ wep_privacy = !!ieee80211_sta_wep_configured(dev);
++ privacy_invoked = !!(ifsta->flags & IEEE80211_STA_PRIVACY_INVOKED);
+
+ ieee80211_rx_bss_put(dev, bss);
+
+- return res;
++ if ((bss_privacy == wep_privacy) || (bss_privacy == privacy_invoked))
++ return 0;
++
++ return 1;
+ }
+
+
+@@ -920,12 +906,7 @@
+
+ printk(KERN_DEBUG "%s: replying to auth challenge\n", dev->name);
+ pos = mgmt->u.auth.variable;
+- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+- == ParseFailed) {
+- printk(KERN_DEBUG "%s: failed to parse Auth(challenge)\n",
+- dev->name);
+- return;
+- }
++ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+ if (!elems.challenge) {
+ printk(KERN_DEBUG "%s: no challenge IE in shared key auth "
+ "frame\n", dev->name);
+@@ -1214,12 +1195,7 @@
+ }
+
+ pos = mgmt->u.assoc_resp.variable;
+- if (ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems)
+- == ParseFailed) {
+- printk(KERN_DEBUG "%s: failed to parse AssocResp\n",
+- dev->name);
+- return;
+- }
++ ieee802_11_parse_elems(pos, len - (pos - (u8 *) mgmt), &elems);
+
+ if (!elems.supp_rates) {
+ printk(KERN_DEBUG "%s: no SuppRates element in AssocResp\n",
+@@ -1231,7 +1207,9 @@
+ * update our stored copy */
+ if (elems.erp_info && elems.erp_info_len >= 1) {
+ struct ieee80211_sta_bss *bss
+- = ieee80211_rx_bss_get(dev, ifsta->bssid);
++ = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ local->hw.conf.channel,
++ ifsta->ssid, ifsta->ssid_len);
+ if (bss) {
+ bss->erp_value = elems.erp_info[0];
+ bss->has_erp_value = 1;
+@@ -1261,7 +1239,9 @@
+ " AP\n", dev->name);
+ return;
+ }
+- bss = ieee80211_rx_bss_get(dev, ifsta->bssid);
++ bss = ieee80211_rx_bss_get(dev, ifsta->bssid,
++ local->hw.conf.channel,
++ ifsta->ssid, ifsta->ssid_len);
+ if (bss) {
+ sta->last_rssi = bss->rssi;
+ sta->last_signal = bss->signal;
+@@ -1337,7 +1317,8 @@
+
+
+ static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid)
++ieee80211_rx_bss_add(struct net_device *dev, u8 *bssid, int channel,
++ u8 *ssid, u8 ssid_len)
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sta_bss *bss;
+@@ -1348,6 +1329,11 @@
+ atomic_inc(&bss->users);
+ atomic_inc(&bss->users);
+ memcpy(bss->bssid, bssid, ETH_ALEN);
++ bss->channel = channel;
++ if (ssid && ssid_len <= IEEE80211_MAX_SSID_LEN) {
++ memcpy(bss->ssid, ssid, ssid_len);
++ bss->ssid_len = ssid_len;
++ }
+
+ spin_lock_bh(&local->sta_bss_lock);
+ /* TODO: order by RSSI? */
+@@ -1359,7 +1345,8 @@
+
+
+ static struct ieee80211_sta_bss *
+-ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid)
++ieee80211_rx_bss_get(struct net_device *dev, u8 *bssid, int channel,
++ u8 *ssid, u8 ssid_len)
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sta_bss *bss;
+@@ -1367,7 +1354,10 @@
+ spin_lock_bh(&local->sta_bss_lock);
+ bss = local->sta_bss_hash[STA_HASH(bssid)];
+ while (bss) {
+- if (memcmp(bss->bssid, bssid, ETH_ALEN) == 0) {
++ if (!memcmp(bss->bssid, bssid, ETH_ALEN) &&
++ bss->channel == channel &&
++ bss->ssid_len == ssid_len &&
++ (ssid_len == 0 || !memcmp(bss->ssid, ssid, ssid_len))) {
+ atomic_inc(&bss->users);
+ break;
+ }
+@@ -1429,7 +1419,7 @@
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee802_11_elems elems;
+ size_t baselen;
+- int channel, invalid = 0, clen;
++ int channel, clen;
+ struct ieee80211_sta_bss *bss;
+ struct sta_info *sta;
+ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+@@ -1473,9 +1463,7 @@
+ #endif /* CONFIG_MAC80211_IBSS_DEBUG */
+ }
+
+- if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
+- &elems) == ParseFailed)
+- invalid = 1;
++ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+
+ if (sdata->type == IEEE80211_IF_TYPE_IBSS && elems.supp_rates &&
+ memcmp(mgmt->bssid, sdata->u.sta.bssid, ETH_ALEN) == 0 &&
+@@ -1533,9 +1521,11 @@
+ else
+ channel = rx_status->channel;
+
+- bss = ieee80211_rx_bss_get(dev, mgmt->bssid);
++ bss = ieee80211_rx_bss_get(dev, mgmt->bssid, channel,
++ elems.ssid, elems.ssid_len);
+ if (!bss) {
+- bss = ieee80211_rx_bss_add(dev, mgmt->bssid);
++ bss = ieee80211_rx_bss_add(dev, mgmt->bssid, channel,
++ elems.ssid, elems.ssid_len);
+ if (!bss)
+ return;
+ } else {
+@@ -1561,10 +1551,6 @@
+
+ bss->beacon_int = le16_to_cpu(mgmt->u.beacon.beacon_int);
+ bss->capability = le16_to_cpu(mgmt->u.beacon.capab_info);
+- if (elems.ssid && elems.ssid_len <= IEEE80211_MAX_SSID_LEN) {
+- memcpy(bss->ssid, elems.ssid, elems.ssid_len);
+- bss->ssid_len = elems.ssid_len;
+- }
+
+ bss->supp_rates_len = 0;
+ if (elems.supp_rates) {
+@@ -1635,7 +1621,6 @@
+
+
+ bss->hw_mode = rx_status->phymode;
+- bss->channel = channel;
+ bss->freq = rx_status->freq;
+ if (channel != rx_status->channel &&
+ (bss->hw_mode == MODE_IEEE80211G ||
+@@ -1695,9 +1680,7 @@
+ if (baselen > len)
+ return;
+
+- if (ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen,
+- &elems) == ParseFailed)
+- return;
++ ieee802_11_parse_elems(mgmt->u.beacon.variable, len - baselen, &elems);
+
+ if (elems.erp_info && elems.erp_info_len >= 1)
+ ieee80211_handle_erp_ie(dev, elems.erp_info[0]);
+@@ -2098,7 +2081,8 @@
+ {
+ int tmp, hidden_ssid;
+
+- if (!memcmp(ifsta->ssid, ssid, ssid_len))
++ if (ssid_len == ifsta->ssid_len &&
++ !memcmp(ifsta->ssid, ssid, ssid_len))
+ return 1;
+
+ if (ifsta->flags & IEEE80211_STA_AUTO_BSSID_SEL)
+@@ -2357,7 +2341,7 @@
+ {
+ struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+ struct ieee80211_sta_bss *bss;
+- struct ieee80211_sub_if_data *sdata;
++ struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ struct ieee80211_hw_mode *mode;
+ u8 bssid[ETH_ALEN], *pos;
+ int i;
+@@ -2379,18 +2363,17 @@
+ printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID " MAC_FMT "\n",
+ dev->name, MAC_ARG(bssid));
+
+- bss = ieee80211_rx_bss_add(dev, bssid);
++ bss = ieee80211_rx_bss_add(dev, bssid, local->hw.conf.channel,
++ sdata->u.sta.ssid, sdata->u.sta.ssid_len);
+ if (!bss)
+ return -ENOMEM;
+
+- sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+ mode = local->oper_hw_mode;
+
+ if (local->hw.conf.beacon_int == 0)
+ local->hw.conf.beacon_int = 100;
+ bss->beacon_int = local->hw.conf.beacon_int;
+ bss->hw_mode = local->hw.conf.phymode;
+- bss->channel = local->hw.conf.channel;
+ bss->freq = local->hw.conf.freq;
+ bss->last_update = jiffies;
+ bss->capability = WLAN_CAPABILITY_IBSS;
+@@ -2448,7 +2431,8 @@
+ MAC_FMT "\n", MAC_ARG(bssid), MAC_ARG(ifsta->bssid));
+ #endif /* CONFIG_MAC80211_IBSS_DEBUG */
+ if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0 &&
+- (bss = ieee80211_rx_bss_get(dev, bssid))) {
++ (bss = ieee80211_rx_bss_get(dev, bssid, local->hw.conf.channel,
++ ifsta->ssid, ifsta->ssid_len))) {
+ printk(KERN_DEBUG "%s: Selected IBSS BSSID " MAC_FMT
+ " based on configured SSID\n",
+ dev->name, MAC_ARG(bssid));
+Index: mac80211/net/mac80211/Kconfig
+===================================================================
+--- mac80211.orig/net/mac80211/Kconfig 2007-11-11 15:45:23.225494151 +0100
++++ mac80211/net/mac80211/Kconfig 2007-11-11 15:45:30.449905846 +0100
+@@ -13,6 +13,18 @@
+ This option enables the hardware independent IEEE 802.11
+ networking stack.
+
++config MAC80211_RCSIMPLE
++ bool "'simple' rate control algorithm" if EMBEDDED
++ default y
++ depends on MAC80211
++ help
++ This option allows you to turn off the 'simple' rate
++ control algorithm in mac80211. If you do turn it off,
++ you absolutely need another rate control algorithm.
++
++ Say Y unless you know you will have another algorithm
++ available.
++
+ config MAC80211_LEDS
+ bool "Enable LED triggers"
+ depends on MAC80211 && LEDS_TRIGGERS
+Index: mac80211/net/mac80211/Makefile
+===================================================================
+--- mac80211.orig/net/mac80211/Makefile 2007-11-11 15:45:23.233494609 +0100
++++ mac80211/net/mac80211/Makefile 2007-11-11 15:45:30.449905846 +0100
+@@ -1,8 +1,9 @@
+-obj-$(CONFIG_MAC80211) += mac80211.o rc80211_simple.o
++obj-$(CONFIG_MAC80211) += mac80211.o
+
+ mac80211-objs-$(CONFIG_MAC80211_LEDS) += ieee80211_led.o
+ mac80211-objs-$(CONFIG_MAC80211_DEBUGFS) += debugfs.o debugfs_sta.o debugfs_netdev.o debugfs_key.o
+ mac80211-objs-$(CONFIG_NET_SCHED) += wme.o
++mac80211-objs-$(CONFIG_MAC80211_RCSIMPLE) += rc80211_simple.o
+
+ mac80211-objs := \
+ ieee80211.o \
+Index: mac80211/net/mac80211/rc80211_simple.c
+===================================================================
+--- mac80211.orig/net/mac80211/rc80211_simple.c 2007-11-11 15:45:23.237494839 +0100
++++ mac80211/net/mac80211/rc80211_simple.c 2007-11-11 15:45:30.449905846 +0100
+@@ -7,7 +7,6 @@
+ * published by the Free Software Foundation.
+ */
+
+-#include <linux/module.h>
+ #include <linux/init.h>
+ #include <linux/netdevice.h>
+ #include <linux/types.h>
+@@ -29,8 +28,6 @@
+ #define RATE_CONTROL_INTERVAL (HZ / 20)
+ #define RATE_CONTROL_MIN_TX 10
+
+-MODULE_ALIAS("rc80211_default");
+-
+ static void rate_control_rate_inc(struct ieee80211_local *local,
+ struct sta_info *sta)
+ {
+@@ -393,8 +390,7 @@
+ }
+ #endif
+
+-static struct rate_control_ops rate_control_simple = {
+- .module = THIS_MODULE,
++struct rate_control_ops mac80211_rcsimple = {
+ .name = "simple",
+ .tx_status = rate_control_simple_tx_status,
+ .get_rate = rate_control_simple_get_rate,
+@@ -409,22 +405,3 @@
+ .remove_sta_debugfs = rate_control_simple_remove_sta_debugfs,
+ #endif
+ };
+-
+-
+-static int __init rate_control_simple_init(void)
+-{
+- return ieee80211_rate_control_register(&rate_control_simple);
+-}
+-
+-
+-static void __exit rate_control_simple_exit(void)
+-{
+- ieee80211_rate_control_unregister(&rate_control_simple);
+-}
+-
+-
+-subsys_initcall(rate_control_simple_init);
+-module_exit(rate_control_simple_exit);
+-
+-MODULE_DESCRIPTION("Simple rate control algorithm for ieee80211");
+-MODULE_LICENSE("GPL");
+Index: mac80211/net/mac80211/rx.c
+===================================================================
+--- mac80211.orig/net/mac80211/rx.c 2007-11-11 15:45:23.245495291 +0100
++++ mac80211/net/mac80211/rx.c 2007-11-11 15:45:30.449905846 +0100
+@@ -509,9 +509,11 @@
+ rx->key->tx_rx_count++;
+ /* TODO: add threshold stuff again */
+ } else {
++#ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: RX protected frame,"
+ " but have no key\n", rx->dev->name);
++#endif /* CONFIG_MAC80211_DEBUG */
+ return TXRX_DROP;
+ }
+
+Index: mac80211/net/mac80211/wep.c
+===================================================================
+--- mac80211.orig/net/mac80211/wep.c 2007-11-11 15:45:23.253495749 +0100
++++ mac80211/net/mac80211/wep.c 2007-11-11 15:45:30.449905846 +0100
+@@ -16,7 +16,7 @@
+ #include <linux/crypto.h>
+ #include <linux/err.h>
+ #include <linux/mm.h>
+-#include <asm/scatterlist.h>
++#include <linux/scatterlist.h>
+
+ #include <net/mac80211.h>
+ #include "ieee80211_i.h"
+@@ -138,9 +138,7 @@
+ *icv = cpu_to_le32(~crc32_le(~0, data, data_len));
+
+ crypto_blkcipher_setkey(tfm, rc4key, klen);
+- sg.page = virt_to_page(data);
+- sg.offset = offset_in_page(data);
+- sg.length = data_len + WEP_ICV_LEN;
++ sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
+ crypto_blkcipher_encrypt(&desc, &sg, &sg, sg.length);
+ }
+
+@@ -204,9 +202,7 @@
+ __le32 crc;
+
+ crypto_blkcipher_setkey(tfm, rc4key, klen);
+- sg.page = virt_to_page(data);
+- sg.offset = offset_in_page(data);
+- sg.length = data_len + WEP_ICV_LEN;
++ sg_init_one(&sg, data, data_len + WEP_ICV_LEN);
+ crypto_blkcipher_decrypt(&desc, &sg, &sg, sg.length);
+
+ crc = cpu_to_le32(~crc32_le(~0, data, data_len));
+@@ -318,9 +314,11 @@
+
+ if (!(rx->u.rx.status->flag & RX_FLAG_DECRYPTED)) {
+ if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) {
++#ifdef CONFIG_MAC80211_DEBUG
+ if (net_ratelimit())
+ printk(KERN_DEBUG "%s: RX WEP frame, decrypt "
+ "failed\n", rx->dev->name);
++#endif /* CONFIG_MAC80211_DEBUG */
+ return TXRX_DROP;
+ }
+ } else if (!(rx->u.rx.status->flag & RX_FLAG_IV_STRIPPED)) {
+Index: mac80211/net/wireless/Kconfig
+===================================================================
+--- mac80211.orig/net/wireless/Kconfig 2007-11-11 15:45:23.261496205 +0100
++++ mac80211/net/wireless/Kconfig 2007-11-11 15:45:30.453906075 +0100
+@@ -3,7 +3,7 @@
+
+ config NL80211
+ bool "nl80211 new netlink interface support"
+- depends CFG80211
++ depends on CFG80211
+ default y
+ ---help---
+ This option turns on the new netlink interface