From patchwork Tue Feb 23 15:19:55 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Helmut Schaa X-Patchwork-Id: 81474 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.3/8.14.3) with ESMTP id o1NFK6Nk014043 for ; Tue, 23 Feb 2010 15:20:07 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752281Ab0BWPUF (ORCPT ); Tue, 23 Feb 2010 10:20:05 -0500 Received: from mail-fx0-f219.google.com ([209.85.220.219]:62608 "EHLO mail-fx0-f219.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751998Ab0BWPUE (ORCPT ); Tue, 23 Feb 2010 10:20:04 -0500 Received: by fxm19 with SMTP id 19so3918664fxm.21 for ; Tue, 23 Feb 2010 07:20:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=googlemail.com; s=gamma; h=domainkey-signature:received:received:from:to:subject:date :user-agent:cc:mime-version:content-type:content-transfer-encoding :message-id; bh=MnFN6eKjT2DfBOnuxZqq7a4cmvuEhZPfDYyfmj/yugQ=; b=rY54PLBgBdmPesRBt4HC3+eaicojDhGDAphItNqZUsp0H73T4IQvlOL9e4DGoGubUH Usw2CNFr8WZk6HbKlhkpHW6hh8v54OF5dnjKVOZl9nW3cvFcZ1rIcvB37kV2/X1OooVK DBrhpkiSWap0pc1HfEjZmiwTgBkYUXXHh0xTY= DomainKey-Signature: a=rsa-sha1; c=nofws; d=googlemail.com; s=gamma; h=from:to:subject:date:user-agent:cc:mime-version:content-type :content-transfer-encoding:message-id; b=rWIEsR0zmpSQYX0eVJT9yzV8psX0fxzgYH6v5C1esL16mbZoow+G+vOrPxreGYKwn/ nCgv/svc7TEOkEgucpkvqQTAN+5AgA5QJiemPtSRU0bIMM5Y9alciqb+v5U3kVmNRNsR 9JB5A/meBj/FPDS+m4Z9Da/y1iWPVKt2D+I0g= Received: by 10.223.62.83 with SMTP id w19mr174864fah.22.1266938401561; Tue, 23 Feb 2010 07:20:01 -0800 (PST) Received: from helmutmobil2.localnet (p5495EDDC.dip.t-dialin.net [84.149.237.220]) by mx.google.com with ESMTPS id b17sm7516342fka.13.2010.02.23.07.19.58 (version=TLSv1/SSLv3 cipher=RC4-MD5); Tue, 23 Feb 2010 07:19:59 -0800 (PST) From: Helmut Schaa To: linux-wireless@vger.kernel.org Subject: [RFC] Improve software scan timing Date: Tue, 23 Feb 2010 16:19:55 +0100 User-Agent: KMail/1.12.0 (Linux/2.6.33-rc8-wl-default; KDE/4.4.0; x86_64; ; ) Cc: Johannes Berg , Kalle Valo MIME-Version: 1.0 Message-Id: <201002231619.55189.helmut.schaa@googlemail.com> Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Tue, 23 Feb 2010 15:20:07 +0000 (UTC) diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 241533e..b841264 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -745,6 +745,7 @@ struct ieee80211_local { int scan_channel_idx; int scan_ies_len; + unsigned long leave_oper_channel_time; enum mac80211_scan_state next_scan_state; struct delayed_work scan_work; struct ieee80211_sub_if_data *scan_sdata; diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index b822dce..f5694b9 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c @@ -14,6 +14,8 @@ #include #include +#include +#include #include #include "ieee80211_i.h" @@ -321,6 +323,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) ieee80211_offchannel_stop_beaconing(local); + local->leave_oper_channel_time = 0; local->next_scan_state = SCAN_DECISION; local->scan_channel_idx = 0; @@ -425,11 +428,26 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, return rc; } +static unsigned long +ieee80211_scan_get_channel_time(struct ieee80211_channel *chan) +{ + /* + * TODO: channel switching also consumes quite some time, + * add that delay as well to get a better estimation + */ + if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) + return IEEE80211_PASSIVE_CHANNEL_TIME; + return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME; +} + static int ieee80211_scan_state_decision(struct ieee80211_local *local, unsigned long *next_delay) { bool associated = false; + bool tx_empty = true; + bool bad_latency; struct ieee80211_sub_if_data *sdata; + struct ieee80211_channel *next_chan; /* if no more bands/channels left, complete scan and advance to the idle state */ if (local->scan_channel_idx >= local->scan_req->n_channels) { @@ -437,7 +455,10 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, return 1; } - /* check if at least one STA interface is associated */ + /* + * check if at least one STA interface is associated + * and if it has pending tx frames + */ mutex_lock(&local->iflist_mtx); list_for_each_entry(sdata, &local->interfaces, list) { if (!ieee80211_sdata_running(sdata)) @@ -446,7 +467,10 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, if (sdata->vif.type == NL80211_IFTYPE_STATION) { if (sdata->u.mgd.associated) { associated = true; - break; + if (!qdisc_all_tx_empty(sdata->dev)) { + tx_empty = false; + break; + } } } } @@ -455,11 +479,24 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local, if (local->scan_channel) { /* * we're currently scanning a different channel, let's - * switch back to the operating channel now if at least - * one interface is associated. Otherwise just scan the - * next channel + * see if we can scan another channel without interfering + * with the current traffic situation. + * + * Since we don't know if the AP has pending frames for us + * we can only check for our tx queues and use the current + * pm_qos requirements for rx. Hence, if no tx traffic occurs + * at all we will scan as many channels in a row as the pm_qos + * latency allows us to. + * + * Otherwise switch back to the operating channel. */ - if (associated) + next_chan = local->scan_req->channels[local->scan_channel_idx]; + bad_latency = time_after(jiffies + + ieee80211_scan_get_channel_time(next_chan), + local->leave_oper_channel_time + + usecs_to_jiffies(pm_qos_requirement(PM_QOS_NETWORK_LATENCY))); + + if (associated && ( !tx_empty || bad_latency)) local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; else local->next_scan_state = SCAN_SET_CHANNEL; @@ -491,6 +528,9 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca else *next_delay = HZ / 10; + /* remember when we left the operating channel */ + local->leave_oper_channel_time = jiffies; + /* advance to the next channel to be scanned */ local->next_scan_state = SCAN_SET_CHANNEL; } @@ -510,6 +550,7 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); + local->leave_oper_channel_time = jiffies; *next_delay = HZ / 5; local->next_scan_state = SCAN_DECISION; }