diff options
Diffstat (limited to 'package/mac80211/patches/000-mac80211_update.patch')
-rw-r--r-- | package/mac80211/patches/000-mac80211_update.patch | 933 |
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 0000000000..7a1a1e271b --- /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 |