On Wednesday 28 February 2007 16:44, Michael Wu wrote: > On Wednesday 28 February 2007 16:42, Michael Wu wrote: > > This makes scans switch STA interfaces into PS mode so the AP queues > > frames destined for us while we are scanning. This is achieved by sending > > a nullfunc data frame with the PS mode bit set before scanning commences, > > and a PS poll frame after scanning is completed. > > Er. I should update the description too.. > And drop the ps_poll part since we don't use the ps poll frame now.. -- d80211: switch STA interfaces to PS mode during scan From: Michael Wu <flamingice@xxxxxxxxxxxx> This makes scans switch STA interfaces into PS mode so the AP queues frames destined for us while we are scanning. This is achieved by sending a nullfunc data frame with the PS mode bit set before scanning commences, and a nullfunc data frame without the PS mode bit set after scanning is completed. Signed-off-by: Michael Wu <flamingice@xxxxxxxxxxxx> --- net/mac80211/ieee80211_sta.c | 51 +++++++++++++++++++++++++++++++++++------- 1 files changed, 43 insertions(+), 8 deletions(-) diff --git a/net/mac80211/ieee80211_sta.c b/net/mac80211/ieee80211_sta.c index ce7dc28..087f176 100644 --- a/net/mac80211/ieee80211_sta.c +++ b/net/mac80211/ieee80211_sta.c @@ -2520,6 +2520,37 @@ int ieee80211_sta_set_bssid(struct net_d } +static void ieee80211_send_nullfunc(struct ieee80211_local *local, + struct ieee80211_sub_if_data *sdata, + int powersave) +{ + struct sk_buff *skb; + struct ieee80211_hdr *nullfunc; + u16 fc; + + skb = dev_alloc_skb(local->hw.extra_tx_headroom + 24); + if (!skb) { + printk(KERN_DEBUG "%s: failed to allocate buffer for nullfunc " + "frame\n", sdata->dev->name); + return; + } + skb_reserve(skb, local->hw.extra_tx_headroom); + + nullfunc = (struct ieee80211_hdr *) skb_put(skb, 24); + memset(nullfunc, 0, 24); + fc = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC | + IEEE80211_FCTL_TODS; + if (powersave) + fc |= IEEE80211_FCTL_PM; + nullfunc->frame_control = cpu_to_le16(fc); + memcpy(nullfunc->addr1, sdata->u.sta.bssid, ETH_ALEN); + memcpy(nullfunc->addr2, sdata->dev->dev_addr, ETH_ALEN); + memcpy(nullfunc->addr3, sdata->u.sta.bssid, ETH_ALEN); + + ieee80211_sta_tx(sdata->dev, skb, 0); +} + + void ieee80211_scan_completed(struct ieee80211_hw *hw) { struct ieee80211_local *local = hw_to_local(hw); @@ -2541,10 +2572,12 @@ void ieee80211_scan_completed(struct iee spin_lock_bh(&local->sub_if_lock); list_for_each_entry(sdata, &local->sub_if_list, list) { - netif_wake_queue(sdata->dev); - - if (sdata->type == IEEE80211_IF_TYPE_STA) + if (sdata->type == IEEE80211_IF_TYPE_STA) { + if (sdata->u.sta.associated) + ieee80211_send_nullfunc(local, sdata, 0); ieee80211_sta_timer((unsigned long)&sdata->u.sta); + } + netif_wake_queue(sdata->dev); } spin_unlock_bh(&local->sub_if_lock); @@ -2664,9 +2697,6 @@ static int ieee80211_sta_start_scan(stru * ResultCode: SUCCESS, INVALID_PARAMETERS */ - /* TODO: if assoc, move to power save mode for the duration of the - * scan */ - if (local->sta_scanning) { if (local->scan_dev == dev) return 0; @@ -2688,8 +2718,12 @@ static int ieee80211_sta_start_scan(stru local->sta_scanning = 1; spin_lock_bh(&local->sub_if_lock); - list_for_each_entry(sdata, &local->sub_if_list, list) + list_for_each_entry(sdata, &local->sub_if_list, list) { netif_stop_queue(sdata->dev); + if (sdata->type == IEEE80211_IF_TYPE_STA && + sdata->u.sta.associated) + ieee80211_send_nullfunc(local, sdata, 1); + } spin_unlock_bh(&local->sub_if_lock); if (ssid) { @@ -2703,7 +2737,8 @@ static int ieee80211_sta_start_scan(stru list); local->scan_channel_idx = 0; local->scan_dev = dev; - schedule_delayed_work(&local->scan_work, 0); + /* TODO: start scan as soon as all nullfunc frames are ACKed */ + schedule_delayed_work(&local->scan_work, IEEE80211_CHANNEL_TIME); return 0; }
Attachment:
pgpGZEKH9JaSX.pgp
Description: PGP signature