Instead of just passing the cfg80211-requested IEs, pass the locally generated ones as well. Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx> --- include/net/mac80211.h | 13 +++++--- net/mac80211/ieee80211_i.h | 6 +++ net/mac80211/main.c | 8 +---- net/mac80211/scan.c | 21 ++++++++++++- net/mac80211/util.c | 72 ++++++++++++++++++++++++++------------------- 5 files changed, 79 insertions(+), 41 deletions(-) --- wireless-testing.orig/include/net/mac80211.h 2009-03-26 17:19:39.000000000 +0100 +++ wireless-testing/include/net/mac80211.h 2009-03-26 17:21:47.000000000 +0100 @@ -1330,11 +1330,14 @@ enum ieee80211_ampdu_mlme_action { * the scan state machine in stack. The scan must honour the channel * configuration done by the regulatory agent in the wiphy's * registered bands. The hardware (or the driver) needs to make sure - * that power save is disabled. When the scan finishes, - * ieee80211_scan_completed() must be called; note that it also must - * be called when the scan cannot finish because the hardware is - * turned off! Anything else is a bug! Returns a negative error code - * which will be seen in userspace. + * that power save is disabled. + * The @req ie/ie_len members are rewritten by mac80211 to contain the + * entire IEs after the SSID, so that drivers need not look at these + * at all but just send them after the SSID -- mac80211 includes the + * (extended) supported rates and HT information (where applicable). + * When the scan finishes, ieee80211_scan_completed() must be called; + * note that it also must be called when the scan cannot finish due to + * any error unless this callback returned a negative error code. * * @sw_scan_start: Notifier function that is called just before a software scan * is started. Can be NULL, if the driver doesn't need this notification. --- wireless-testing.orig/net/mac80211/ieee80211_i.h 2009-03-26 17:37:21.000000000 +0100 +++ wireless-testing/net/mac80211/ieee80211_i.h 2009-03-26 18:21:59.000000000 +0100 @@ -51,6 +51,10 @@ struct ieee80211_local; * increased memory use (about 2 kB of RAM per entry). */ #define IEEE80211_FRAGMENT_MAX 4 +/* cfg80211 only supports 32 rates */ +#define MAC80211_PREQ_IE_LEN ( 2 + 32 /* SSID */\ + + 4 + 32 /* (ext) supp rates */) + /* * Time after which we ignore scan results and no longer report/use * them in any way. @@ -1093,6 +1097,8 @@ void ieee80211_send_auth(struct ieee8021 u16 transaction, u16 auth_alg, u8 *extra, size_t extra_len, const u8 *bssid, int encrypt); +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + u8 *ie, size_t ie_len); void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len, u8 *ie, size_t ie_len); --- wireless-testing.orig/net/mac80211/util.c 2009-03-26 17:22:38.000000000 +0100 +++ wireless-testing/net/mac80211/util.c 2009-03-26 18:21:59.000000000 +0100 @@ -832,16 +832,54 @@ void ieee80211_send_auth(struct ieee8021 ieee80211_tx_skb(sdata, skb, encrypt); } +int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, + u8 *ie, size_t ie_len) +{ + struct ieee80211_supported_band *sband; + u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; + int i; + + sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; + + pos = buffer; + + *pos++ = WLAN_EID_SUPP_RATES; + supp_rates_len = pos; + *pos++ = 0; + + for (i = 0; i < sband->n_bitrates; i++) { + struct ieee80211_rate *rate = &sband->bitrates[i]; + + if (esupp_rates_len) { + *esupp_rates_len += 1; + } else if (*supp_rates_len == 8) { + *pos++ = WLAN_EID_EXT_SUPP_RATES; + esupp_rates_len = pos; + *pos++ = 1; + } else + *supp_rates_len += 1; + + *pos++ = rate->bitrate / 5; + } + + /* if adding more here, adjust MAC80211_PREQ_IE_LEN */ + + if (ie) { + memcpy(pos, ie, ie_len); + pos += ie_len; + } + + return pos - buffer; +} + void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, u8 *ssid, size_t ssid_len, u8 *ie, size_t ie_len) { struct ieee80211_local *local = sdata->local; - struct ieee80211_supported_band *sband; struct sk_buff *skb; struct ieee80211_mgmt *mgmt; - u8 *pos, *supp_rates, *esupp_rates = NULL; - int i; + u8 *pos; skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + ie_len); @@ -868,33 +906,9 @@ void ieee80211_send_probe_req(struct iee *pos++ = WLAN_EID_SSID; *pos++ = ssid_len; memcpy(pos, ssid, ssid_len); + pos += ssid_len; - supp_rates = skb_put(skb, 2); - supp_rates[0] = WLAN_EID_SUPP_RATES; - supp_rates[1] = 0; - sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; - - for (i = 0; i < sband->n_bitrates; i++) { - struct ieee80211_rate *rate = &sband->bitrates[i]; - if (esupp_rates) { - pos = skb_put(skb, 1); - esupp_rates[1]++; - } else if (supp_rates[1] == 8) { - esupp_rates = skb_put(skb, 3); - esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES; - esupp_rates[1] = 1; - pos = &esupp_rates[2]; - } else { - pos = skb_put(skb, 1); - supp_rates[1]++; - } - *pos = rate->bitrate / 5; - } - - /* if adding more here, adjust max_scan_ie_len */ - - if (ie) - memcpy(skb_put(skb, ie_len), ie, ie_len); + skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); ieee80211_tx_skb(sdata, skb, 0); } --- wireless-testing.orig/net/mac80211/main.c 2009-03-26 17:39:50.000000000 +0100 +++ wireless-testing/net/mac80211/main.c 2009-03-26 17:41:48.000000000 +0100 @@ -728,12 +728,8 @@ struct ieee80211_hw *ieee80211_alloc_hw( if (!ops->hw_scan) { /* For hw_scan, driver needs to set these up. */ wiphy->max_scan_ssids = 4; - - /* we support a maximum of 32 rates in cfg80211 */ - wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN - - 2 - 32 /* SSID */ - - 4 - 32 /* (ext) supp rates */; - + wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN - + MAC80211_PREQ_IE_LEN; } /* Yes, putting cfg80211_bss into ieee80211_bss is a hack */ --- wireless-testing.orig/net/mac80211/scan.c 2009-03-26 17:41:58.000000000 +0100 +++ wireless-testing/net/mac80211/scan.c 2009-03-26 17:47:08.000000000 +0100 @@ -286,6 +286,12 @@ void ieee80211_scan_completed(struct iee if (WARN_ON(!local->scan_req)) return; + if (local->hw_scanning) { + kfree(local->scan_req->ie); + local->scan_req->ie = NULL; + local->scan_req->ie_len = 0; + } + if (local->scan_req != &local->int_scan_req) cfg80211_scan_done(local->scan_req, aborted); local->scan_req = NULL; @@ -456,12 +462,25 @@ int ieee80211_start_scan(struct ieee8021 } if (local->ops->hw_scan) { - int rc; + u8 *ies; + int rc, ielen; + + ies = kmalloc(MAC80211_PREQ_IE_LEN + req->ie_len, GFP_KERNEL); + if (!ies) + return -ENOMEM; + + ielen = ieee80211_build_preq_ies(local, ies, + req->ie, req->ie_len); + req->ie = ies; + req->ie_len = ielen; local->hw_scanning = true; rc = drv_hw_scan(local, req); if (rc) { local->hw_scanning = false; + kfree(ies); + req->ie_len = 0; + req->ie = NULL; return rc; } local->scan_sdata = scan_sdata; -- To unsubscribe from this list: send the line "unsubscribe linux-wireless" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html