* Re: [PATCH 5/7] mac80211: implement basic background scanning
From: Johannes Berg @ 2009-07-23 10:59 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <200907231248.36825.helmut.schaa@googlemail.com>
[-- Attachment #1: Type: text/plain, Size: 789 bytes --]
On Thu, 2009-07-23 at 12:48 +0200, Helmut Schaa wrote:
> Am Donnerstag, 23. Juli 2009 schrieb Johannes Berg:
> > On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> > > Introduce a new scan flag "SCAN_BG_SCANNING" which basically tells us
> > > that we are currently scanning but may as well be on the operating channel
> > > to RX/TX data whereas "SCAN_SW_SCANNING" tells us that we are currently
> > > on a different channel for scanning. While "SCAN_BG_SCANNING" is set
> > > during the whole scan "SCAN_SW_SCANNING" is set when leaving the operating
> > > channel and unset when coming back.
> >
> > I think you got that description wrong :)
>
> Argh, yes. Should I respin the whole series?
Not for all I care, just resend this one as a reply to it?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 7/7] cfg80211: increase scan result expire time
From: Helmut Schaa @ 2009-07-23 10:50 UTC (permalink / raw)
To: Johannes Berg; +Cc: linville, linux-wireless
In-Reply-To: <1248345595.19121.25.camel@johannes.local>
Am Donnerstag, 23. Juli 2009 schrieb Johannes Berg:
> On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> > Using background scanning in mac80211 the time a scan needs to
> > finish can exceed 10 seconds. Hence, increase the scan results
> > expire time to 15 seconds which should be sufficient.
> >
> > Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
>
> Heh.
;)
Maybe we could later use a dynamic expire time based on the time
the last scan took or something similar. But for now 15 seconds
should suffice.
> Acked-by: Johannes Berg <johannes@sipsolutions.net>
>
> johannes
>
> > ---
> >
> > net/wireless/scan.c | 2 +-
> > 1 files changed, 1 insertions(+), 1 deletions(-)
> >
> > diff --git a/net/wireless/scan.c b/net/wireless/scan.c
> > index 4ad8b4b..0850b98 100644
> > --- a/net/wireless/scan.c
> > +++ b/net/wireless/scan.c
> > @@ -15,7 +15,7 @@
> > #include "core.h"
> > #include "nl80211.h"
> >
> > -#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
> > +#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
> >
> > void __cfg80211_scan_done(struct work_struct *wk)
> > {
> >
> >
>
^ permalink raw reply
* Re: [PATCH 4/7] mac80211: Replace {sw, hw}_scanning variables with a bitfield
From: Johannes Berg @ 2009-07-23 10:48 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <200907231246.56210.helmut.schaa@googlemail.com>
[-- Attachment #1: Type: text/plain, Size: 763 bytes --]
On Thu, 2009-07-23 at 12:46 +0200, Helmut Schaa wrote:
> Am Donnerstag, 23. Juli 2009 schrieb Johannes Berg:
> > On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> > > Use a bitfield to store the current scan mode instead of two boolean
> > > variables {sw,hw}_scanning. This patch does not introduce functional
> > > changes but allows us to enhance the scan flags later (for example
> > > for background scanning).
> >
> > > + if (test_bit(SCAN_SW_SCANNING, &local->scanning))
> >
> > Do we actually need atomic bitops?
>
> No (at least not yet). That's why I used __set_bit. test_bit seems to not
> have a non-atomic equivalent. Or did you mean not to use *_bit functions
> at all?
Sorry, you're right, I got confused.
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 5/7] mac80211: implement basic background scanning
From: Helmut Schaa @ 2009-07-23 10:48 UTC (permalink / raw)
To: Johannes Berg; +Cc: linville, linux-wireless
In-Reply-To: <1248345547.19121.23.camel@johannes.local>
Am Donnerstag, 23. Juli 2009 schrieb Johannes Berg:
> On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> > Introduce a new scan flag "SCAN_BG_SCANNING" which basically tells us
> > that we are currently scanning but may as well be on the operating channel
> > to RX/TX data whereas "SCAN_SW_SCANNING" tells us that we are currently
> > on a different channel for scanning. While "SCAN_BG_SCANNING" is set
> > during the whole scan "SCAN_SW_SCANNING" is set when leaving the operating
> > channel and unset when coming back.
>
> I think you got that description wrong :)
Argh, yes. Should I respin the whole series?
> > + * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as
> > + * well be on the operating channel
> > + * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
> > + * determine if we are on the operating channel or not
> > + * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
> > + * gets only set in conjunction with SCAN_SW_SCANNING
>
> johannes
>
^ permalink raw reply
* Re: [PATCH 4/7] mac80211: Replace {sw, hw}_scanning variables with a bitfield
From: Helmut Schaa @ 2009-07-23 10:46 UTC (permalink / raw)
To: Johannes Berg; +Cc: linville, linux-wireless
In-Reply-To: <1248345497.19121.22.camel@johannes.local>
Am Donnerstag, 23. Juli 2009 schrieb Johannes Berg:
> On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> > Use a bitfield to store the current scan mode instead of two boolean
> > variables {sw,hw}_scanning. This patch does not introduce functional
> > changes but allows us to enhance the scan flags later (for example
> > for background scanning).
>
> > + if (test_bit(SCAN_SW_SCANNING, &local->scanning))
>
> Do we actually need atomic bitops?
No (at least not yet). That's why I used __set_bit. test_bit seems to not
have a non-atomic equivalent. Or did you mean not to use *_bit functions
at all?
Helmut
^ permalink raw reply
* Re: [PATCH 7/7] cfg80211: increase scan result expire time
From: Johannes Berg @ 2009-07-23 10:39 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101428.5147.53956.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 890 bytes --]
On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> Using background scanning in mac80211 the time a scan needs to
> finish can exceed 10 seconds. Hence, increase the scan results
> expire time to 15 seconds which should be sufficient.
>
> Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Heh.
Acked-by: Johannes Berg <johannes@sipsolutions.net>
johannes
> ---
>
> net/wireless/scan.c | 2 +-
> 1 files changed, 1 insertions(+), 1 deletions(-)
>
> diff --git a/net/wireless/scan.c b/net/wireless/scan.c
> index 4ad8b4b..0850b98 100644
> --- a/net/wireless/scan.c
> +++ b/net/wireless/scan.c
> @@ -15,7 +15,7 @@
> #include "core.h"
> #include "nl80211.h"
>
> -#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
> +#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
>
> void __cfg80211_scan_done(struct work_struct *wk)
> {
>
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 6/7] mac80211: rename scan_state to next_scan_state
From: Johannes Berg @ 2009-07-23 10:39 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101420.5147.71489.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 4041 bytes --]
On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> Rename scan_state to next_scan_state to better reflect
> what it is used for.
>
> Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> ---
>
> net/mac80211/ieee80211_i.h | 2 +-
> net/mac80211/scan.c | 20 ++++++++++----------
> 2 files changed, 11 insertions(+), 11 deletions(-)
>
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index efda19e..c6b25cb 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -715,7 +715,7 @@ struct ieee80211_local {
> int scan_channel_idx;
> int scan_ies_len;
>
> - enum mac80211_scan_state scan_state;
> + enum mac80211_scan_state next_scan_state;
> struct delayed_work scan_work;
> struct ieee80211_sub_if_data *scan_sdata;
> enum nl80211_channel_type oper_channel_type;
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index d56b9da..b376775 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -374,7 +374,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
> }
> mutex_unlock(&local->iflist_mtx);
>
> - local->scan_state = SCAN_DECISION;
> + local->next_scan_state = SCAN_DECISION;
> local->scan_channel_idx = 0;
>
> spin_lock_bh(&local->filter_lock);
> @@ -505,15 +505,15 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
> * next channel
> */
> if (associated)
> - local->scan_state = SCAN_ENTER_OPER_CHANNEL;
> + local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
> else
> - local->scan_state = SCAN_SET_CHANNEL;
> + local->next_scan_state = SCAN_SET_CHANNEL;
> } else {
> /*
> * we're on the operating channel currently, let's
> * leave that channel now to scan another one
> */
> - local->scan_state = SCAN_LEAVE_OPER_CHANNEL;
> + local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
> }
>
> *next_delay = 0;
> @@ -545,7 +545,7 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca
>
> /* advance to the next channel to be scanned */
> *next_delay = HZ / 10;
> - local->scan_state = SCAN_SET_CHANNEL;
> + local->next_scan_state = SCAN_SET_CHANNEL;
> }
>
> static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
> @@ -577,7 +577,7 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
> __clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
>
> *next_delay = HZ / 5;
> - local->scan_state = SCAN_DECISION;
> + local->next_scan_state = SCAN_DECISION;
> }
>
> static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> @@ -621,13 +621,13 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
> !local->scan_req->n_ssids) {
> *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
> - local->scan_state = SCAN_DECISION;
> + local->next_scan_state = SCAN_DECISION;
> return;
> }
>
> /* active scan, send probes */
> *next_delay = IEEE80211_PROBE_DELAY;
> - local->scan_state = SCAN_SEND_PROBE;
> + local->next_scan_state = SCAN_SEND_PROBE;
> }
>
> static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
> @@ -648,7 +648,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
> * on the channel.
> */
> *next_delay = IEEE80211_CHANNEL_TIME;
> - local->scan_state = SCAN_DECISION;
> + local->next_scan_state = SCAN_DECISION;
> }
>
> void ieee80211_scan_work(struct work_struct *work)
> @@ -693,7 +693,7 @@ void ieee80211_scan_work(struct work_struct *work)
> * without scheduling a new work
> */
> do {
> - switch (local->scan_state) {
> + switch (local->next_scan_state) {
> case SCAN_DECISION:
> if (ieee80211_scan_state_decision(local, &next_delay))
> return;
>
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 5/7] mac80211: implement basic background scanning
From: Johannes Berg @ 2009-07-23 10:39 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101411.5147.78380.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 916 bytes --]
On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> Introduce a new scan flag "SCAN_BG_SCANNING" which basically tells us
> that we are currently scanning but may as well be on the operating channel
> to RX/TX data whereas "SCAN_SW_SCANNING" tells us that we are currently
> on a different channel for scanning. While "SCAN_BG_SCANNING" is set
> during the whole scan "SCAN_SW_SCANNING" is set when leaving the operating
> channel and unset when coming back.
I think you got that description wrong :)
> + * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as
> + * well be on the operating channel
> + * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
> + * determine if we are on the operating channel or not
> + * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
> + * gets only set in conjunction with SCAN_SW_SCANNING
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 4/7] mac80211: Replace {sw, hw}_scanning variables with a bitfield
From: Johannes Berg @ 2009-07-23 10:38 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101403.5147.55273.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 408 bytes --]
On Thu, 2009-07-23 at 12:14 +0200, Helmut Schaa wrote:
> Use a bitfield to store the current scan mode instead of two boolean
> variables {sw,hw}_scanning. This patch does not introduce functional
> changes but allows us to enhance the scan flags later (for example
> for background scanning).
> + if (test_bit(SCAN_SW_SCANNING, &local->scanning))
Do we actually need atomic bitops?
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 3/7] mac80211: introduce a new scan state "decision"
From: Johannes Berg @ 2009-07-23 10:37 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101355.5147.26099.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 4416 bytes --]
On Thu, 2009-07-23 at 12:13 +0200, Helmut Schaa wrote:
> Introduce a new scan state "decision" which is entered after
> every completed scan operation and decides about the next steps.
> At first the decision is in any case to scan the next channel.
> This shouldn't introduce any functional changes.
>
> Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> ---
>
> net/mac80211/ieee80211_i.h | 2 +-
> net/mac80211/scan.c | 40 ++++++++++++++++++++++++++--------------
> 2 files changed, 27 insertions(+), 15 deletions(-)
>
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 6a01771..4166418 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -678,7 +678,7 @@ struct ieee80211_local {
> int scan_channel_idx;
> int scan_ies_len;
>
> - enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
> + enum { SCAN_DECISION, SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
> struct delayed_work scan_work;
> struct ieee80211_sub_if_data *scan_sdata;
> enum nl80211_channel_type oper_channel_type;
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index db122e4..48f910a 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -376,7 +376,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
> }
> mutex_unlock(&local->iflist_mtx);
>
> - local->scan_state = SCAN_SET_CHANNEL;
> + local->scan_state = SCAN_DECISION;
> local->scan_channel_idx = 0;
>
> spin_lock_bh(&local->filter_lock);
> @@ -474,18 +474,27 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
> return rc;
> }
>
> -static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> - unsigned long *next_delay)
> +static int ieee80211_scan_state_decision(struct ieee80211_local *local,
> + unsigned long *next_delay)
> {
> - int skip;
> - struct ieee80211_channel *chan;
> - struct ieee80211_sub_if_data *sdata = local->scan_sdata;
> -
> /* if no more bands/channels left, complete scan */
> if (local->scan_channel_idx >= local->scan_req->n_channels) {
> ieee80211_scan_completed(&local->hw, false);
> return 1;
> }
> +
> + *next_delay = 0;
> + local->scan_state = SCAN_SET_CHANNEL;
> + return 0;
> +}
> +
> +static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> + unsigned long *next_delay)
> +{
> + int skip;
> + struct ieee80211_channel *chan;
> + struct ieee80211_sub_if_data *sdata = local->scan_sdata;
> +
> skip = 0;
> chan = local->scan_req->channels[local->scan_channel_idx];
>
> @@ -505,7 +514,7 @@ static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> local->scan_channel_idx++;
>
> if (skip)
> - return 0;
> + return;
>
> /*
> * Probe delay is used to update the NAV, cf. 11.1.3.2.2
> @@ -520,13 +529,13 @@ static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
> !local->scan_req->n_ssids) {
> *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
> - return 0;
> + local->scan_state = SCAN_DECISION;
> + return;
> }
>
> + /* active scan, send probes */
> *next_delay = IEEE80211_PROBE_DELAY;
> local->scan_state = SCAN_SEND_PROBE;
> -
> - return 0;
> }
>
> static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
> @@ -547,7 +556,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
> * on the channel.
> */
> *next_delay = IEEE80211_CHANNEL_TIME;
> - local->scan_state = SCAN_SET_CHANNEL;
> + local->scan_state = SCAN_DECISION;
> }
>
> void ieee80211_scan_work(struct work_struct *work)
> @@ -593,10 +602,13 @@ void ieee80211_scan_work(struct work_struct *work)
> */
> do {
> switch (local->scan_state) {
> - case SCAN_SET_CHANNEL:
> - if (ieee80211_scan_state_set_channel(local, &next_delay))
> + case SCAN_DECISION:
> + if (ieee80211_scan_state_decision(local, &next_delay))
> return;
> break;
> + case SCAN_SET_CHANNEL:
> + ieee80211_scan_state_set_channel(local, &next_delay);
> + break;
> case SCAN_SEND_PROBE:
> ieee80211_scan_state_send_probe(local, &next_delay);
> break;
>
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 2/7] mac80211: advance the state machine immediately if no delay is needed
From: Johannes Berg @ 2009-07-23 10:36 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101348.5147.92831.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 1445 bytes --]
On Thu, 2009-07-23 at 12:13 +0200, Helmut Schaa wrote:
> Instead of queueing the scan work again without delay just process the
> next state immediately.
>
> Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> ---
>
> net/mac80211/scan.c | 24 +++++++++++++++---------
> 1 files changed, 15 insertions(+), 9 deletions(-)
>
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index 71500f1..db122e4 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -587,15 +587,21 @@ void ieee80211_scan_work(struct work_struct *work)
> return;
> }
>
> - switch (local->scan_state) {
> - case SCAN_SET_CHANNEL:
> - if (ieee80211_scan_state_set_channel(local, &next_delay))
> - return;
> - break;
> - case SCAN_SEND_PROBE:
> - ieee80211_scan_state_send_probe(local, &next_delay);
> - break;
> - }
> + /*
> + * as long as no delay is required advance immediately
> + * without scheduling a new work
> + */
> + do {
> + switch (local->scan_state) {
> + case SCAN_SET_CHANNEL:
> + if (ieee80211_scan_state_set_channel(local, &next_delay))
> + return;
> + break;
> + case SCAN_SEND_PROBE:
> + ieee80211_scan_state_send_probe(local, &next_delay);
> + break;
> + }
> + } while (next_delay == 0);
>
> queue_delayed_work(local->hw.workqueue, &local->scan_work,
> next_delay);
>
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH 1/7] mac80211: refactor the scan code
From: Johannes Berg @ 2009-07-23 10:36 UTC (permalink / raw)
To: Helmut Schaa; +Cc: linville, linux-wireless
In-Reply-To: <20090723101340.5147.17700.stgit@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 5665 bytes --]
On Thu, 2009-07-23 at 12:13 +0200, Helmut Schaa wrote:
> Move the processing of each scan state into its own functions for better
> readability. This patch does not introduce functional changes.
>
> Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
Acked-by: Johannes Berg <johannes@sipsolutions.net>
> ---
>
> net/mac80211/scan.c | 136 +++++++++++++++++++++++++++++----------------------
> 1 files changed, 78 insertions(+), 58 deletions(-)
>
> diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
> index 7482065..71500f1 100644
> --- a/net/mac80211/scan.c
> +++ b/net/mac80211/scan.c
> @@ -474,13 +474,87 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
> return rc;
> }
>
> +static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
> + unsigned long *next_delay)
> +{
> + int skip;
> + struct ieee80211_channel *chan;
> + struct ieee80211_sub_if_data *sdata = local->scan_sdata;
> +
> + /* if no more bands/channels left, complete scan */
> + if (local->scan_channel_idx >= local->scan_req->n_channels) {
> + ieee80211_scan_completed(&local->hw, false);
> + return 1;
> + }
> + skip = 0;
> + chan = local->scan_req->channels[local->scan_channel_idx];
> +
> + if (chan->flags & IEEE80211_CHAN_DISABLED ||
> + (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
> + chan->flags & IEEE80211_CHAN_NO_IBSS))
> + skip = 1;
> +
> + if (!skip) {
> + local->scan_channel = chan;
> + if (ieee80211_hw_config(local,
> + IEEE80211_CONF_CHANGE_CHANNEL))
> + skip = 1;
> + }
> +
> + /* advance state machine to next channel/band */
> + local->scan_channel_idx++;
> +
> + if (skip)
> + return 0;
> +
> + /*
> + * Probe delay is used to update the NAV, cf. 11.1.3.2.2
> + * (which unfortunately doesn't say _why_ step a) is done,
> + * but it waits for the probe delay or until a frame is
> + * received - and the received frame would update the NAV).
> + * For now, we do not support waiting until a frame is
> + * received.
> + *
> + * In any case, it is not necessary for a passive scan.
> + */
> + if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
> + !local->scan_req->n_ssids) {
> + *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
> + return 0;
> + }
> +
> + *next_delay = IEEE80211_PROBE_DELAY;
> + local->scan_state = SCAN_SEND_PROBE;
> +
> + return 0;
> +}
> +
> +static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
> + unsigned long *next_delay)
> +{
> + int i;
> + struct ieee80211_sub_if_data *sdata = local->scan_sdata;
> +
> + for (i = 0; i < local->scan_req->n_ssids; i++)
> + ieee80211_send_probe_req(
> + sdata, NULL,
> + local->scan_req->ssids[i].ssid,
> + local->scan_req->ssids[i].ssid_len,
> + local->scan_req->ie, local->scan_req->ie_len);
> +
> + /*
> + * After sending probe requests, wait for probe responses
> + * on the channel.
> + */
> + *next_delay = IEEE80211_CHANNEL_TIME;
> + local->scan_state = SCAN_SET_CHANNEL;
> +}
> +
> void ieee80211_scan_work(struct work_struct *work)
> {
> struct ieee80211_local *local =
> container_of(work, struct ieee80211_local, scan_work.work);
> struct ieee80211_sub_if_data *sdata = local->scan_sdata;
> - struct ieee80211_channel *chan;
> - int skip, i;
> unsigned long next_delay = 0;
>
> mutex_lock(&local->scan_mtx);
> @@ -515,65 +589,11 @@ void ieee80211_scan_work(struct work_struct *work)
>
> switch (local->scan_state) {
> case SCAN_SET_CHANNEL:
> - /* if no more bands/channels left, complete scan */
> - if (local->scan_channel_idx >= local->scan_req->n_channels) {
> - ieee80211_scan_completed(&local->hw, false);
> + if (ieee80211_scan_state_set_channel(local, &next_delay))
> return;
> - }
> - skip = 0;
> - chan = local->scan_req->channels[local->scan_channel_idx];
> -
> - if (chan->flags & IEEE80211_CHAN_DISABLED ||
> - (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
> - chan->flags & IEEE80211_CHAN_NO_IBSS))
> - skip = 1;
> -
> - if (!skip) {
> - local->scan_channel = chan;
> - if (ieee80211_hw_config(local,
> - IEEE80211_CONF_CHANGE_CHANNEL))
> - skip = 1;
> - }
> -
> - /* advance state machine to next channel/band */
> - local->scan_channel_idx++;
> -
> - if (skip)
> - break;
> -
> - /*
> - * Probe delay is used to update the NAV, cf. 11.1.3.2.2
> - * (which unfortunately doesn't say _why_ step a) is done,
> - * but it waits for the probe delay or until a frame is
> - * received - and the received frame would update the NAV).
> - * For now, we do not support waiting until a frame is
> - * received.
> - *
> - * In any case, it is not necessary for a passive scan.
> - */
> - if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
> - !local->scan_req->n_ssids) {
> - next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
> - break;
> - }
> -
> - next_delay = IEEE80211_PROBE_DELAY;
> - local->scan_state = SCAN_SEND_PROBE;
> break;
> case SCAN_SEND_PROBE:
> - for (i = 0; i < local->scan_req->n_ssids; i++)
> - ieee80211_send_probe_req(
> - sdata, NULL,
> - local->scan_req->ssids[i].ssid,
> - local->scan_req->ssids[i].ssid_len,
> - local->scan_req->ie, local->scan_req->ie_len);
> -
> - /*
> - * After sending probe requests, wait for probe responses
> - * on the channel.
> - */
> - next_delay = IEEE80211_CHANNEL_TIME;
> - local->scan_state = SCAN_SET_CHANNEL;
> + ieee80211_scan_state_send_probe(local, &next_delay);
> break;
> }
>
>
>
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* Re: [PATCH] mac80211: Add a few 802.11n defines for AMPDU parameters
From: Johannes Berg @ 2009-07-23 10:35 UTC (permalink / raw)
To: Sujith; +Cc: linville, linux-wireless
In-Reply-To: <19048.13563.475455.554327@localhost.localdomain>
[-- Attachment #1: Type: text/plain, Size: 332 bytes --]
On Thu, 2009-07-23 at 15:31 +0530, Sujith wrote:
> Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
> ---
> include/linux/ieee80211.h | 25 +++++++++++++++++++++++++
> 1 files changed, 25 insertions(+), 0 deletions(-)
not really mac80211, but anyway
Acked-by: Johannes Berg <johannes@sipsolutions.net>
johannes
[-- Attachment #2: This is a digitally signed message part --]
[-- Type: application/pgp-signature, Size: 801 bytes --]
^ permalink raw reply
* [PATCH 7/7] cfg80211: increase scan result expire time
From: Helmut Schaa @ 2009-07-23 10:14 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Using background scanning in mac80211 the time a scan needs to
finish can exceed 10 seconds. Hence, increase the scan results
expire time to 15 seconds which should be sufficient.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/wireless/scan.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 4ad8b4b..0850b98 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -15,7 +15,7 @@
#include "core.h"
#include "nl80211.h"
-#define IEEE80211_SCAN_RESULT_EXPIRE (10 * HZ)
+#define IEEE80211_SCAN_RESULT_EXPIRE (15 * HZ)
void __cfg80211_scan_done(struct work_struct *wk)
{
^ permalink raw reply related
* [PATCH 6/7] mac80211: rename scan_state to next_scan_state
From: Helmut Schaa @ 2009-07-23 10:14 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Rename scan_state to next_scan_state to better reflect
what it is used for.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/scan.c | 20 ++++++++++----------
2 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index efda19e..c6b25cb 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -715,7 +715,7 @@ struct ieee80211_local {
int scan_channel_idx;
int scan_ies_len;
- enum mac80211_scan_state scan_state;
+ enum mac80211_scan_state next_scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data *scan_sdata;
enum nl80211_channel_type oper_channel_type;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index d56b9da..b376775 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -374,7 +374,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
}
mutex_unlock(&local->iflist_mtx);
- local->scan_state = SCAN_DECISION;
+ local->next_scan_state = SCAN_DECISION;
local->scan_channel_idx = 0;
spin_lock_bh(&local->filter_lock);
@@ -505,15 +505,15 @@ static int ieee80211_scan_state_decision(struct ieee80211_local *local,
* next channel
*/
if (associated)
- local->scan_state = SCAN_ENTER_OPER_CHANNEL;
+ local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
else
- local->scan_state = SCAN_SET_CHANNEL;
+ local->next_scan_state = SCAN_SET_CHANNEL;
} else {
/*
* we're on the operating channel currently, let's
* leave that channel now to scan another one
*/
- local->scan_state = SCAN_LEAVE_OPER_CHANNEL;
+ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
}
*next_delay = 0;
@@ -545,7 +545,7 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca
/* advance to the next channel to be scanned */
*next_delay = HZ / 10;
- local->scan_state = SCAN_SET_CHANNEL;
+ local->next_scan_state = SCAN_SET_CHANNEL;
}
static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
@@ -577,7 +577,7 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
__clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
*next_delay = HZ / 5;
- local->scan_state = SCAN_DECISION;
+ local->next_scan_state = SCAN_DECISION;
}
static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
@@ -621,13 +621,13 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
!local->scan_req->n_ssids) {
*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
- local->scan_state = SCAN_DECISION;
+ local->next_scan_state = SCAN_DECISION;
return;
}
/* active scan, send probes */
*next_delay = IEEE80211_PROBE_DELAY;
- local->scan_state = SCAN_SEND_PROBE;
+ local->next_scan_state = SCAN_SEND_PROBE;
}
static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
@@ -648,7 +648,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
* on the channel.
*/
*next_delay = IEEE80211_CHANNEL_TIME;
- local->scan_state = SCAN_DECISION;
+ local->next_scan_state = SCAN_DECISION;
}
void ieee80211_scan_work(struct work_struct *work)
@@ -693,7 +693,7 @@ void ieee80211_scan_work(struct work_struct *work)
* without scheduling a new work
*/
do {
- switch (local->scan_state) {
+ switch (local->next_scan_state) {
case SCAN_DECISION:
if (ieee80211_scan_state_decision(local, &next_delay))
return;
^ permalink raw reply related
* [PATCH 5/7] mac80211: implement basic background scanning
From: Helmut Schaa @ 2009-07-23 10:14 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Introduce a new scan flag "SCAN_BG_SCANNING" which basically tells us
that we are currently scanning but may as well be on the operating channel
to RX/TX data whereas "SCAN_SW_SCANNING" tells us that we are currently
on a different channel for scanning. While "SCAN_BG_SCANNING" is set
during the whole scan "SCAN_SW_SCANNING" is set when leaving the operating
channel and unset when coming back.
Introduce two new scan states "SCAN_LEAVE_OPER_CHANNEL" and
"SCAN_ENTER_OPER_CHANNEL" which basically implement the functionality we
need to leave the operating channel (send a nullfunc to the AP and stop
the queues) and enter it again (send a nullfunc to the AP and start the
queues again).
Enhance the scan state "SCAN_DECISION" to switch back to the operating
channel after each scanned channel. In the future it sould be simple
to enhance the decision state to scan as much channels in a row as the
qos latency allows us.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/ieee80211_i.h | 36 +++++++++++++-
net/mac80211/rx.c | 6 ++
net/mac80211/scan.c | 117 +++++++++++++++++++++++++++++++++++++++++---
net/mac80211/tx.c | 2 -
4 files changed, 148 insertions(+), 13 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 783a125..efda19e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -570,9 +570,41 @@ enum queue_stop_reason {
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
};
+/**
+ * mac80211 scan flags - currently active scan mode
+ *
+ * @SCAN_SW_SCANNING: We're currently in the process of scanning but may as
+ * well be on the operating channel
+ * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
+ * determine if we are on the operating channel or not
+ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
+ * gets only set in conjunction with SCAN_SW_SCANNING
+ */
enum {
SCAN_SW_SCANNING,
- SCAN_HW_SCANNING
+ SCAN_HW_SCANNING,
+ SCAN_OFF_CHANNEL,
+};
+
+/**
+ * enum mac80211_scan_state - scan state machine states
+ *
+ * @SCAN_DECISION: Main entry point to the scan state machine, this state
+ * determines if we should keep on scanning or switch back to the
+ * operating channel
+ * @SCAN_SET_CHANNEL: Set the next channel to be scanned
+ * @SCAN_SEND_PROBE: Send probe requests and wait for probe responses
+ * @SCAN_LEAVE_OPER_CHANNEL: Leave the operating channel, notify the AP
+ * about us leaving the channel and stop all associated STA interfaces
+ * @SCAN_ENTER_OPER_CHANNEL: Enter the operating channel again, notify the
+ * AP about us being back and restart all associated STA interfaces
+ */
+enum mac80211_scan_state {
+ SCAN_DECISION,
+ SCAN_SET_CHANNEL,
+ SCAN_SEND_PROBE,
+ SCAN_LEAVE_OPER_CHANNEL,
+ SCAN_ENTER_OPER_CHANNEL,
};
struct ieee80211_local {
@@ -683,7 +715,7 @@ struct ieee80211_local {
int scan_channel_idx;
int scan_ies_len;
- enum { SCAN_DECISION, SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+ enum mac80211_scan_state scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data *scan_sdata;
enum nl80211_channel_type oper_channel_type;
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index b1bebc1..dd192b3 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -421,7 +421,8 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning)))
return ieee80211_scan_rx(rx->sdata, skb);
- if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) {
+ if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning) &&
+ (rx->flags & IEEE80211_RX_IN_SCAN))) {
/* drop all the other packets during a software scan anyway */
if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
dev_kfree_skb(skb);
@@ -2136,7 +2137,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
return;
}
- if (unlikely(local->scanning))
+ if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+ test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
rx.flags |= IEEE80211_RX_IN_SCAN;
ieee80211_parse_qos(&rx);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 4233c3d..d56b9da 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -365,12 +365,11 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
ieee80211_bss_info_change_notify(
sdata, BSS_CHANGED_BEACON_ENABLED);
- if (sdata->vif.type == NL80211_IFTYPE_STATION) {
- if (sdata->u.mgd.associated) {
- netif_tx_stop_all_queues(sdata->dev);
- ieee80211_scan_ps_enable(sdata);
- }
- } else
+ /*
+ * only handle non-STA interfaces here, STA interfaces
+ * are handled in the scan state machine
+ */
+ if (sdata->vif.type != NL80211_IFTYPE_STATION)
netif_tx_stop_all_queues(sdata->dev);
}
mutex_unlock(&local->iflist_mtx);
@@ -474,17 +473,113 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
static int ieee80211_scan_state_decision(struct ieee80211_local *local,
unsigned long *next_delay)
{
- /* if no more bands/channels left, complete scan */
+ bool associated = false;
+ struct ieee80211_sub_if_data *sdata;
+
+ /* if no more bands/channels left, complete scan and advance to the idle state */
if (local->scan_channel_idx >= local->scan_req->n_channels) {
ieee80211_scan_completed(&local->hw, false);
return 1;
}
+ /* check if at least one STA interface is associated */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated) {
+ associated = true;
+ break;
+ }
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ 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
+ */
+ if (associated)
+ local->scan_state = SCAN_ENTER_OPER_CHANNEL;
+ else
+ local->scan_state = SCAN_SET_CHANNEL;
+ } else {
+ /*
+ * we're on the operating channel currently, let's
+ * leave that channel now to scan another one
+ */
+ local->scan_state = SCAN_LEAVE_OPER_CHANNEL;
+ }
+
*next_delay = 0;
- local->scan_state = SCAN_SET_CHANNEL;
return 0;
}
+static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ struct ieee80211_sub_if_data *sdata;
+
+ /*
+ * notify the AP about us leaving the channel and stop all STA interfaces
+ */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ netif_tx_stop_all_queues(sdata->dev);
+ if (sdata->u.mgd.associated)
+ ieee80211_scan_ps_enable(sdata);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ __set_bit(SCAN_OFF_CHANNEL, &local->scanning);
+
+ /* advance to the next channel to be scanned */
+ *next_delay = HZ / 10;
+ local->scan_state = SCAN_SET_CHANNEL;
+}
+
+static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
+ /* switch back to the operating channel */
+ local->scan_channel = NULL;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ /*
+ * notify the AP about us being back and restart all STA interfaces
+ */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!netif_running(sdata->dev))
+ continue;
+
+ /* Tell AP we're back */
+ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated)
+ ieee80211_scan_ps_disable(sdata);
+ netif_tx_wake_all_queues(sdata->dev);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
+
+ *next_delay = HZ / 5;
+ local->scan_state = SCAN_DECISION;
+}
+
static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
unsigned long *next_delay)
{
@@ -609,6 +704,12 @@ void ieee80211_scan_work(struct work_struct *work)
case SCAN_SEND_PROBE:
ieee80211_scan_state_send_probe(local, &next_delay);
break;
+ case SCAN_LEAVE_OPER_CHANNEL:
+ ieee80211_scan_state_leave_oper_channel(local, &next_delay);
+ break;
+ case SCAN_ENTER_OPER_CHANNEL:
+ ieee80211_scan_state_enter_oper_channel(local, &next_delay);
+ break;
}
} while (next_delay == 0);
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 61739ab..275bc15 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -192,7 +192,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
return TX_CONTINUE;
- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
+ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
!ieee80211_is_probe_req(hdr->frame_control) &&
!ieee80211_is_nullfunc(hdr->frame_control))
/*
^ permalink raw reply related
* [PATCH 4/7] mac80211: Replace {sw, hw}_scanning variables with a bitfield
From: Helmut Schaa @ 2009-07-23 10:14 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Use a bitfield to store the current scan mode instead of two boolean
variables {sw,hw}_scanning. This patch does not introduce functional
changes but allows us to enhance the scan flags later (for example
for background scanning).
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/ibss.c | 2 +-
net/mac80211/ieee80211_i.h | 7 ++++++-
net/mac80211/iface.c | 4 ++--
net/mac80211/main.c | 2 +-
net/mac80211/mesh.c | 2 +-
net/mac80211/mlme.c | 8 ++++----
net/mac80211/rx.c | 6 +++---
net/mac80211/scan.c | 23 ++++++++++-------------
net/mac80211/tx.c | 6 +++---
9 files changed, 31 insertions(+), 29 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8e22200..6e3cca6 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -742,7 +742,7 @@ static void ieee80211_ibss_work(struct work_struct *work)
if (!netif_running(sdata->dev))
return;
- if (local->sw_scanning || local->hw_scanning)
+ if (local->scanning)
return;
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC))
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 4166418..783a125 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -570,6 +570,11 @@ enum queue_stop_reason {
IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
};
+enum {
+ SCAN_SW_SCANNING,
+ SCAN_HW_SCANNING
+};
+
struct ieee80211_local {
/* embed the driver visible part.
* don't cast (use the static inlines below), but we keep
@@ -668,7 +673,7 @@ struct ieee80211_local {
/* Scanning and BSS list */
struct mutex scan_mtx;
- bool sw_scanning, hw_scanning;
+ unsigned long scanning;
struct cfg80211_ssid scan_ssid;
struct cfg80211_scan_request int_scan_req;
struct cfg80211_scan_request *scan_req;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 2f797a8..ee9cede 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -515,7 +515,7 @@ static int ieee80211_stop(struct net_device *dev)
* the scan_sdata is NULL already don't send out a
* scan event to userspace -- the scan is incomplete.
*/
- if (local->sw_scanning)
+ if (test_bit(SCAN_SW_SCANNING, &local->scanning))
ieee80211_scan_completed(&local->hw, true);
}
@@ -905,7 +905,7 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
struct ieee80211_sub_if_data *sdata;
int count = 0;
- if (local->hw_scanning || local->sw_scanning)
+ if (local->scanning)
return ieee80211_idle_off(local, "scanning");
list_for_each_entry(sdata, &local->interfaces, list) {
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 3234f37..6d7b4cd 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -198,7 +198,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
}
if (changed & BSS_CHANGED_BEACON_ENABLED) {
- if (local->sw_scanning) {
+ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
sdata->vif.bss_conf.enable_beacon = false;
} else {
/*
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 8a97b14..9a38269 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -597,7 +597,7 @@ static void ieee80211_mesh_work(struct work_struct *work)
if (!netif_running(sdata->dev))
return;
- if (local->sw_scanning || local->hw_scanning)
+ if (local->scanning)
return;
while ((skb = skb_dequeue(&ifmsh->skb_queue)))
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 523c0d9..52b6f83 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -581,7 +581,7 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
if (!ifmgd->associated)
return;
- if (sdata->local->sw_scanning || sdata->local->hw_scanning)
+ if (sdata->local->scanning)
return;
/* Disregard subsequent beacons if we are already running a timer
@@ -639,7 +639,7 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
* If we are scanning right now then the parameters will
* take effect when scan finishes.
*/
- if (local->hw_scanning || local->sw_scanning)
+ if (local->scanning)
return;
if (conf->dynamic_ps_timeout > 0 &&
@@ -2038,7 +2038,7 @@ static void ieee80211_sta_work(struct work_struct *work)
if (!netif_running(sdata->dev))
return;
- if (local->sw_scanning || local->hw_scanning)
+ if (local->scanning)
return;
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
@@ -2213,7 +2213,7 @@ static void ieee80211_sta_monitor_work(struct work_struct *work)
container_of(work, struct ieee80211_sub_if_data,
u.mgd.monitor_work);
- if (sdata->local->sw_scanning || sdata->local->hw_scanning)
+ if (sdata->local->scanning)
return;
ieee80211_mgd_probe_ap(sdata, false);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 66c797c..b1bebc1 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -418,10 +418,10 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
struct ieee80211_local *local = rx->local;
struct sk_buff *skb = rx->skb;
- if (unlikely(local->hw_scanning))
+ if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning)))
return ieee80211_scan_rx(rx->sdata, skb);
- if (unlikely(local->sw_scanning)) {
+ if (unlikely(test_bit(SCAN_SW_SCANNING, &local->scanning))) {
/* drop all the other packets during a software scan anyway */
if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
dev_kfree_skb(skb);
@@ -2136,7 +2136,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
return;
}
- if (unlikely(local->sw_scanning || local->hw_scanning))
+ if (unlikely(local->scanning))
rx.flags |= IEEE80211_RX_IN_SCAN;
ieee80211_parse_qos(&rx);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 48f910a..4233c3d 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -265,7 +265,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
mutex_lock(&local->scan_mtx);
- if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) {
+ if (WARN_ON(!local->scanning)) {
mutex_unlock(&local->scan_mtx);
return;
}
@@ -275,16 +275,15 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
return;
}
- if (local->hw_scanning)
+ if (test_bit(SCAN_HW_SCANNING, &local->scanning))
ieee80211_restore_scan_ies(local);
if (local->scan_req != &local->int_scan_req)
cfg80211_scan_done(local->scan_req, aborted);
local->scan_req = NULL;
- was_hw_scan = local->hw_scanning;
- local->hw_scanning = false;
- local->sw_scanning = false;
+ was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
+ local->scanning = 0;
local->scan_channel = NULL;
/* we only have to protect scan_req and hw/sw scan */
@@ -434,9 +433,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
}
if (local->ops->hw_scan)
- local->hw_scanning = true;
+ __set_bit(SCAN_HW_SCANNING, &local->scanning);
else
- local->sw_scanning = true;
+ __set_bit(SCAN_SW_SCANNING, &local->scanning);
/*
* Kicking off the scan need not be protected,
* only the scan variable stuff, since now
@@ -459,11 +458,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
mutex_lock(&local->scan_mtx);
if (rc) {
- if (local->ops->hw_scan) {
- local->hw_scanning = false;
+ if (local->ops->hw_scan)
ieee80211_restore_scan_ies(local);
- } else
- local->sw_scanning = false;
+ local->scanning = 0;
ieee80211_recalc_idle(local);
@@ -572,7 +569,7 @@ void ieee80211_scan_work(struct work_struct *work)
return;
}
- if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) {
+ if (local->scan_req && !local->scanning) {
struct cfg80211_scan_request *req = local->scan_req;
int rc;
@@ -663,7 +660,7 @@ void ieee80211_scan_cancel(struct ieee80211_local *local)
* queued -- mostly at suspend under RTNL.
*/
mutex_lock(&local->scan_mtx);
- swscan = local->sw_scanning;
+ swscan = test_bit(SCAN_SW_SCANNING, &local->scanning);
mutex_unlock(&local->scan_mtx);
if (swscan)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index c11cbbd..61739ab 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -192,7 +192,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
return TX_CONTINUE;
- if (unlikely(tx->local->sw_scanning) &&
+ if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
!ieee80211_is_probe_req(hdr->frame_control) &&
!ieee80211_is_nullfunc(hdr->frame_control))
/*
@@ -551,7 +551,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx)
* Lets not bother rate control if we're associated and cannot
* talk to the sta. This should not happen.
*/
- if (WARN((tx->local->sw_scanning) &&
+ if (WARN(test_bit(SCAN_SW_SCANNING, &tx->local->scanning) &&
(sta_flags & WLAN_STA_ASSOC) &&
!rate_usable_index_exists(sband, &tx->sta->sta),
"%s: Dropped data frame as no usable bitrate found while "
@@ -1396,7 +1396,7 @@ static void ieee80211_xmit(struct ieee80211_sub_if_data *sdata,
if ((local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) &&
local->hw.conf.dynamic_ps_timeout > 0 &&
- !local->sw_scanning && !local->hw_scanning && local->ps_sdata) {
+ !(local->scanning) && local->ps_sdata) {
if (local->hw.conf.flags & IEEE80211_CONF_PS) {
ieee80211_stop_queues_by_reason(&local->hw,
IEEE80211_QUEUE_STOP_REASON_PS);
^ permalink raw reply related
* [PATCH 3/7] mac80211: introduce a new scan state "decision"
From: Helmut Schaa @ 2009-07-23 10:13 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Introduce a new scan state "decision" which is entered after
every completed scan operation and decides about the next steps.
At first the decision is in any case to scan the next channel.
This shouldn't introduce any functional changes.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/ieee80211_i.h | 2 +-
net/mac80211/scan.c | 40 ++++++++++++++++++++++++++--------------
2 files changed, 27 insertions(+), 15 deletions(-)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 6a01771..4166418 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -678,7 +678,7 @@ struct ieee80211_local {
int scan_channel_idx;
int scan_ies_len;
- enum { SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
+ enum { SCAN_DECISION, SCAN_SET_CHANNEL, SCAN_SEND_PROBE } scan_state;
struct delayed_work scan_work;
struct ieee80211_sub_if_data *scan_sdata;
enum nl80211_channel_type oper_channel_type;
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index db122e4..48f910a 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -376,7 +376,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
}
mutex_unlock(&local->iflist_mtx);
- local->scan_state = SCAN_SET_CHANNEL;
+ local->scan_state = SCAN_DECISION;
local->scan_channel_idx = 0;
spin_lock_bh(&local->filter_lock);
@@ -474,18 +474,27 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
return rc;
}
-static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
- unsigned long *next_delay)
+static int ieee80211_scan_state_decision(struct ieee80211_local *local,
+ unsigned long *next_delay)
{
- int skip;
- struct ieee80211_channel *chan;
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
-
/* if no more bands/channels left, complete scan */
if (local->scan_channel_idx >= local->scan_req->n_channels) {
ieee80211_scan_completed(&local->hw, false);
return 1;
}
+
+ *next_delay = 0;
+ local->scan_state = SCAN_SET_CHANNEL;
+ return 0;
+}
+
+static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ int skip;
+ struct ieee80211_channel *chan;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
skip = 0;
chan = local->scan_req->channels[local->scan_channel_idx];
@@ -505,7 +514,7 @@ static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
local->scan_channel_idx++;
if (skip)
- return 0;
+ return;
/*
* Probe delay is used to update the NAV, cf. 11.1.3.2.2
@@ -520,13 +529,13 @@ static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
!local->scan_req->n_ssids) {
*next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
- return 0;
+ local->scan_state = SCAN_DECISION;
+ return;
}
+ /* active scan, send probes */
*next_delay = IEEE80211_PROBE_DELAY;
local->scan_state = SCAN_SEND_PROBE;
-
- return 0;
}
static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
@@ -547,7 +556,7 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
* on the channel.
*/
*next_delay = IEEE80211_CHANNEL_TIME;
- local->scan_state = SCAN_SET_CHANNEL;
+ local->scan_state = SCAN_DECISION;
}
void ieee80211_scan_work(struct work_struct *work)
@@ -593,10 +602,13 @@ void ieee80211_scan_work(struct work_struct *work)
*/
do {
switch (local->scan_state) {
- case SCAN_SET_CHANNEL:
- if (ieee80211_scan_state_set_channel(local, &next_delay))
+ case SCAN_DECISION:
+ if (ieee80211_scan_state_decision(local, &next_delay))
return;
break;
+ case SCAN_SET_CHANNEL:
+ ieee80211_scan_state_set_channel(local, &next_delay);
+ break;
case SCAN_SEND_PROBE:
ieee80211_scan_state_send_probe(local, &next_delay);
break;
^ permalink raw reply related
* [PATCH 2/7] mac80211: advance the state machine immediately if no delay is needed
From: Helmut Schaa @ 2009-07-23 10:13 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Instead of queueing the scan work again without delay just process the
next state immediately.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/scan.c | 24 +++++++++++++++---------
1 files changed, 15 insertions(+), 9 deletions(-)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 71500f1..db122e4 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -587,15 +587,21 @@ void ieee80211_scan_work(struct work_struct *work)
return;
}
- switch (local->scan_state) {
- case SCAN_SET_CHANNEL:
- if (ieee80211_scan_state_set_channel(local, &next_delay))
- return;
- break;
- case SCAN_SEND_PROBE:
- ieee80211_scan_state_send_probe(local, &next_delay);
- break;
- }
+ /*
+ * as long as no delay is required advance immediately
+ * without scheduling a new work
+ */
+ do {
+ switch (local->scan_state) {
+ case SCAN_SET_CHANNEL:
+ if (ieee80211_scan_state_set_channel(local, &next_delay))
+ return;
+ break;
+ case SCAN_SEND_PROBE:
+ ieee80211_scan_state_send_probe(local, &next_delay);
+ break;
+ }
+ } while (next_delay == 0);
queue_delayed_work(local->hw.workqueue, &local->scan_work,
next_delay);
^ permalink raw reply related
* [PATCH 1/7] mac80211: refactor the scan code
From: Helmut Schaa @ 2009-07-23 10:13 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
In-Reply-To: <20090723100732.5147.73989.stgit@localhost.localdomain>
Move the processing of each scan state into its own functions for better
readability. This patch does not introduce functional changes.
Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com>
---
net/mac80211/scan.c | 136 +++++++++++++++++++++++++++++----------------------
1 files changed, 78 insertions(+), 58 deletions(-)
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 7482065..71500f1 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -474,13 +474,87 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
return rc;
}
+static int ieee80211_scan_state_set_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ int skip;
+ struct ieee80211_channel *chan;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
+ /* if no more bands/channels left, complete scan */
+ if (local->scan_channel_idx >= local->scan_req->n_channels) {
+ ieee80211_scan_completed(&local->hw, false);
+ return 1;
+ }
+ skip = 0;
+ chan = local->scan_req->channels[local->scan_channel_idx];
+
+ if (chan->flags & IEEE80211_CHAN_DISABLED ||
+ (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
+ chan->flags & IEEE80211_CHAN_NO_IBSS))
+ skip = 1;
+
+ if (!skip) {
+ local->scan_channel = chan;
+ if (ieee80211_hw_config(local,
+ IEEE80211_CONF_CHANGE_CHANNEL))
+ skip = 1;
+ }
+
+ /* advance state machine to next channel/band */
+ local->scan_channel_idx++;
+
+ if (skip)
+ return 0;
+
+ /*
+ * Probe delay is used to update the NAV, cf. 11.1.3.2.2
+ * (which unfortunately doesn't say _why_ step a) is done,
+ * but it waits for the probe delay or until a frame is
+ * received - and the received frame would update the NAV).
+ * For now, we do not support waiting until a frame is
+ * received.
+ *
+ * In any case, it is not necessary for a passive scan.
+ */
+ if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+ !local->scan_req->n_ssids) {
+ *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
+ return 0;
+ }
+
+ *next_delay = IEEE80211_PROBE_DELAY;
+ local->scan_state = SCAN_SEND_PROBE;
+
+ return 0;
+}
+
+static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
+ unsigned long *next_delay)
+{
+ int i;
+ struct ieee80211_sub_if_data *sdata = local->scan_sdata;
+
+ for (i = 0; i < local->scan_req->n_ssids; i++)
+ ieee80211_send_probe_req(
+ sdata, NULL,
+ local->scan_req->ssids[i].ssid,
+ local->scan_req->ssids[i].ssid_len,
+ local->scan_req->ie, local->scan_req->ie_len);
+
+ /*
+ * After sending probe requests, wait for probe responses
+ * on the channel.
+ */
+ *next_delay = IEEE80211_CHANNEL_TIME;
+ local->scan_state = SCAN_SET_CHANNEL;
+}
+
void ieee80211_scan_work(struct work_struct *work)
{
struct ieee80211_local *local =
container_of(work, struct ieee80211_local, scan_work.work);
struct ieee80211_sub_if_data *sdata = local->scan_sdata;
- struct ieee80211_channel *chan;
- int skip, i;
unsigned long next_delay = 0;
mutex_lock(&local->scan_mtx);
@@ -515,65 +589,11 @@ void ieee80211_scan_work(struct work_struct *work)
switch (local->scan_state) {
case SCAN_SET_CHANNEL:
- /* if no more bands/channels left, complete scan */
- if (local->scan_channel_idx >= local->scan_req->n_channels) {
- ieee80211_scan_completed(&local->hw, false);
+ if (ieee80211_scan_state_set_channel(local, &next_delay))
return;
- }
- skip = 0;
- chan = local->scan_req->channels[local->scan_channel_idx];
-
- if (chan->flags & IEEE80211_CHAN_DISABLED ||
- (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
- chan->flags & IEEE80211_CHAN_NO_IBSS))
- skip = 1;
-
- if (!skip) {
- local->scan_channel = chan;
- if (ieee80211_hw_config(local,
- IEEE80211_CONF_CHANGE_CHANNEL))
- skip = 1;
- }
-
- /* advance state machine to next channel/band */
- local->scan_channel_idx++;
-
- if (skip)
- break;
-
- /*
- * Probe delay is used to update the NAV, cf. 11.1.3.2.2
- * (which unfortunately doesn't say _why_ step a) is done,
- * but it waits for the probe delay or until a frame is
- * received - and the received frame would update the NAV).
- * For now, we do not support waiting until a frame is
- * received.
- *
- * In any case, it is not necessary for a passive scan.
- */
- if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
- !local->scan_req->n_ssids) {
- next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
- break;
- }
-
- next_delay = IEEE80211_PROBE_DELAY;
- local->scan_state = SCAN_SEND_PROBE;
break;
case SCAN_SEND_PROBE:
- for (i = 0; i < local->scan_req->n_ssids; i++)
- ieee80211_send_probe_req(
- sdata, NULL,
- local->scan_req->ssids[i].ssid,
- local->scan_req->ssids[i].ssid_len,
- local->scan_req->ie, local->scan_req->ie_len);
-
- /*
- * After sending probe requests, wait for probe responses
- * on the channel.
- */
- next_delay = IEEE80211_CHANNEL_TIME;
- local->scan_state = SCAN_SET_CHANNEL;
+ ieee80211_scan_state_send_probe(local, &next_delay);
break;
}
^ permalink raw reply related
* [PATCH 0/7] implement background scan
From: Helmut Schaa @ 2009-07-23 10:13 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, johannes
This patch series implements basic background scanning in mac80211
by interrupting the scan after each scanned channel to allow RX/TX.
I only tested the patches on current wireless-testing with iwlagn
in sw-scan mode and it works fine already. Nevertheless, it would
be great if somebody could test the patches on other hardware as well.
A scan now takes ~13s on my iwl4965 with a total of 31 channels
(17 passive channels) while associated. Two possibilities for the
future to reduce the time a scan takes:
- leave the operating channel as soon as RX and TX were idle for
a small period of time (currently we just stay 250ms on the
operating channel after each scanned channel).
- Scan multiple channels in a row if the qos latency allows us to
do so.
Helmut
---
Helmut Schaa (7):
cfg80211: increase scan result expire time
mac80211: rename scan_state to next_scan_state
mac80211: implement basic background scanning
mac80211: Replace {sw,hw}_scanning variables with a bitfield
mac80211: introduce a new scan state "decision"
mac80211: advance the state machine immediately if no delay is needed
mac80211: refactor the scan code
net/mac80211/ibss.c | 2
net/mac80211/ieee80211_i.h | 41 ++++++
net/mac80211/iface.c | 4 -
net/mac80211/main.c | 2
net/mac80211/mesh.c | 2
net/mac80211/mlme.c | 8 +
net/mac80211/rx.c | 8 +
net/mac80211/scan.c | 300 ++++++++++++++++++++++++++++++++------------
net/mac80211/tx.c | 6 -
net/wireless/scan.c | 2
10 files changed, 275 insertions(+), 100 deletions(-)
--
Signature
^ permalink raw reply
* [PATCH 6/6] ath9k: Remove a few redundant variables/macros
From: Sujith @ 2009-07-23 10:02 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
drivers/net/wireless/ath/ath9k/xmit.c | 24 ++++++++++--------------
2 files changed, 10 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 9d01d99..e94e8f9 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -190,7 +190,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define ATH_AGGR_MIN_QDEPTH 2
#define ATH_AMPDU_SUBFRAME_DEFAULT 32
#define ATH_AMPDU_LIMIT_MAX (64 * 1024 - 1)
-#define ATH_AMPDU_LIMIT_DEFAULT ATH_AMPDU_LIMIT_MAX
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index fd07aa1..b7806e2 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -458,7 +458,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
struct ieee80211_tx_rate *rates;
struct ath_tx_info_priv *tx_info_priv;
u32 max_4ms_framelen, frmlen;
- u16 aggr_limit, legacy = 0, maxampdu;
+ u16 aggr_limit, legacy = 0;
int i;
skb = bf->bf_mpdu;
@@ -493,16 +493,15 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
if (tx_info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE || legacy)
return 0;
- aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_DEFAULT);
+ aggr_limit = min(max_4ms_framelen, (u32)ATH_AMPDU_LIMIT_MAX);
/*
* h/w can accept aggregates upto 16 bit lengths (65535).
* The IE, however can hold upto 65536, which shows up here
* as zero. Ignore 65536 since we are constrained by hw.
*/
- maxampdu = tid->an->maxampdu;
- if (maxampdu)
- aggr_limit = min(aggr_limit, maxampdu);
+ if (tid->an->maxampdu)
+ aggr_limit = min(aggr_limit, tid->an->maxampdu);
return aggr_limit;
}
@@ -510,7 +509,6 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
/*
* Returns the number of delimiters to be added to
* meet the minimum required mpdudensity.
- * caller should make sure that the rate is HT rate .
*/
static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
struct ath_buf *bf, u16 frmlen)
@@ -518,7 +516,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
const struct ath_rate_table *rt = sc->cur_rate_table;
struct sk_buff *skb = bf->bf_mpdu;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
- u32 nsymbits, nsymbols, mpdudensity;
+ u32 nsymbits, nsymbols;
u16 minlen;
u8 rc, flags, rix;
int width, half_gi, ndelim, mindelim;
@@ -540,14 +538,12 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
* on highest rate in rate series (i.e. first rate) to determine
* required minimum length for subframe. Take into account
* whether high rate is 20 or 40Mhz and half or full GI.
- */
- mpdudensity = tid->an->mpdudensity;
-
- /*
+ *
* If there is no mpdu density restriction, no further calculation
* is needed.
*/
- if (mpdudensity == 0)
+
+ if (tid->an->mpdudensity == 0)
return ndelim;
rix = tx_info->control.rates[0].idx;
@@ -557,9 +553,9 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
if (half_gi)
- nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(mpdudensity);
+ nsymbols = NUM_SYMBOLS_PER_USEC_HALFGI(tid->an->mpdudensity);
else
- nsymbols = NUM_SYMBOLS_PER_USEC(mpdudensity);
+ nsymbols = NUM_SYMBOLS_PER_USEC(tid->an->mpdudensity);
if (nsymbols == 0)
nsymbols = 1;
--
1.6.3.3
^ permalink raw reply related
* [PATCH 5/6] ath9k: Cleanup return values
From: Sujith @ 2009-07-23 10:02 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
Cleanup aggregation start/stop function interfaces.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 6 +++---
drivers/net/wireless/ath/ath9k/main.c | 14 +++-----------
drivers/net/wireless/ath/ath9k/xmit.c | 25 +++++++++----------------
3 files changed, 15 insertions(+), 30 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index d3c1633..9d01d99 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -362,9 +362,9 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
void ath_tx_tasklet(struct ath_softc *sc);
void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb);
bool ath_tx_aggr_check(struct ath_softc *sc, struct ath_node *an, u8 tidno);
-int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tid, u16 *ssn);
-int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
+void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn);
+void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
/********/
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index fb84dd8..f2fa333 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2671,19 +2671,11 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_RX_STOP:
break;
case IEEE80211_AMPDU_TX_START:
- ret = ath_tx_aggr_start(sc, sta, tid, ssn);
- if (ret < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "Unable to start TX aggregation\n");
- else
- ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
+ ath_tx_aggr_start(sc, sta, tid, ssn);
+ ieee80211_start_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_STOP:
- ret = ath_tx_aggr_stop(sc, sta, tid);
- if (ret < 0)
- DPRINTF(sc, ATH_DBG_FATAL,
- "Unable to stop TX aggregation\n");
-
+ ath_tx_aggr_stop(sc, sta, tid);
ieee80211_stop_tx_ba_cb_irqsafe(hw, sta->addr, tid);
break;
case IEEE80211_AMPDU_TX_OPERATIONAL:
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 8a8d7ed..fd07aa1 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -701,25 +701,20 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
status != ATH_AGGR_BAW_CLOSED);
}
-int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
- u16 tid, u16 *ssn)
+void ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
+ u16 tid, u16 *ssn)
{
struct ath_atx_tid *txtid;
struct ath_node *an;
an = (struct ath_node *)sta->drv_priv;
-
- if (sc->sc_flags & SC_OP_TXAGGR) {
- txtid = ATH_AN_2_TID(an, tid);
- txtid->state |= AGGR_ADDBA_PROGRESS;
- ath_tx_pause_tid(sc, txtid);
- *ssn = txtid->seq_start;
- }
-
- return 0;
+ txtid = ATH_AN_2_TID(an, tid);
+ txtid->state |= AGGR_ADDBA_PROGRESS;
+ ath_tx_pause_tid(sc, txtid);
+ *ssn = txtid->seq_start;
}
-int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
+void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
{
struct ath_node *an = (struct ath_node *)sta->drv_priv;
struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid);
@@ -729,11 +724,11 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
INIT_LIST_HEAD(&bf_head);
if (txtid->state & AGGR_CLEANUP)
- return 0;
+ return;
if (!(txtid->state & AGGR_ADDBA_COMPLETE)) {
txtid->state &= ~AGGR_ADDBA_PROGRESS;
- return 0;
+ return;
}
ath_tx_pause_tid(sc, txtid);
@@ -762,8 +757,6 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
txtid->state &= ~AGGR_ADDBA_COMPLETE;
ath_tx_flush_tid(sc, txtid);
}
-
- return 0;
}
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
--
1.6.3.3
^ permalink raw reply related
* [PATCH 4/6] ath9k: Remove redundant HT macros
From: Sujith @ 2009-07-23 10:02 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
These can be obtained from mac80211.
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 2 --
drivers/net/wireless/ath/ath9k/main.c | 8 +++-----
2 files changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 1308cac..d3c1633 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -194,8 +194,6 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
#define IEEE80211_SEQ_SEQ_SHIFT 4
#define IEEE80211_SEQ_MAX 4096
-#define IEEE80211_MIN_AMPDU_BUF 0x8
-#define IEEE80211_HTCAP_MAXRXAMPDU_FACTOR 13
#define IEEE80211_WEP_IVLEN 3
#define IEEE80211_WEP_KIDLEN 1
#define IEEE80211_WEP_CRCLEN 4
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index b053c1c..fb84dd8 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -462,7 +462,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta)
if (sc->sc_flags & SC_OP_TXAGGR) {
ath_tx_node_init(sc, an);
- an->maxampdu = 1 << (IEEE80211_HTCAP_MAXRXAMPDU_FACTOR +
+ an->maxampdu = 1 << (IEEE80211_HT_MAX_AMPDU_FACTOR +
sta->ht_cap.ampdu_factor);
an->mpdudensity = parse_mpdudensity(sta->ht_cap.ampdu_density);
an->last_rssi = ATH_RSSI_DUMMY_MARKER;
@@ -888,8 +888,6 @@ static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key)
static void setup_ht_cap(struct ath_softc *sc,
struct ieee80211_sta_ht_cap *ht_info)
{
-#define ATH9K_HT_CAP_MAXRXAMPDU_65536 0x3 /* 2 ^ 16 */
-#define ATH9K_HT_CAP_MPDUDENSITY_8 0x6 /* 8 usec */
u8 tx_streams, rx_streams;
ht_info->ht_supported = true;
@@ -898,8 +896,8 @@ static void setup_ht_cap(struct ath_softc *sc,
IEEE80211_HT_CAP_SGI_40 |
IEEE80211_HT_CAP_DSSSCCK40;
- ht_info->ampdu_factor = ATH9K_HT_CAP_MAXRXAMPDU_65536;
- ht_info->ampdu_density = ATH9K_HT_CAP_MPDUDENSITY_8;
+ ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_8;
/* set up supported mcs set */
memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
--
1.6.3.3
^ permalink raw reply related
* [PATCH 3/6] ath9k: Add debug counters for TX
From: Sujith @ 2009-07-23 10:02 UTC (permalink / raw)
To: linville; +Cc: linux-wireless
Location: ath9k/phy#/xmit
Signed-off-by: Sujith <Sujith.Manoharan@atheros.com>
---
drivers/net/wireless/ath/ath9k/ath9k.h | 1 -
drivers/net/wireless/ath/ath9k/debug.c | 85 ++++++++++++++++++++++++++++++++
drivers/net/wireless/ath/ath9k/debug.h | 54 ++++++++++++++++++++
drivers/net/wireless/ath/ath9k/xmit.c | 34 ++++++++-----
4 files changed, 160 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 751885a..1308cac 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -240,7 +240,6 @@ struct ath_txq {
spinlock_t axq_lock;
u32 axq_depth;
u8 axq_aggr_depth;
- u32 axq_totalqueued;
bool stopped;
bool axq_tx_inprogress;
struct ath_buf *axq_linkbuf;
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 9f99f00..9e36920 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -486,6 +486,83 @@ static const struct file_operations fops_wiphy = {
.owner = THIS_MODULE
};
+#define PR(str, elem) \
+ do { \
+ len += snprintf(buf + len, size - len, \
+ "%s%13u%11u%10u%10u\n", str, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BE]].elem, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_BK]].elem, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VI]].elem, \
+ sc->debug.stats.txstats[sc->tx.hwq_map[ATH9K_WME_AC_VO]].elem); \
+} while(0)
+
+static ssize_t read_file_xmit(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_softc *sc = file->private_data;
+ char *buf;
+ unsigned int len = 0, size = 2048;
+ ssize_t retval = 0;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return 0;
+
+ len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
+
+ PR("MPDUs Queued: ", queued);
+ PR("MPDUs Completed: ", completed);
+ PR("Aggregates: ", a_aggr);
+ PR("AMPDUs Queued: ", a_queued);
+ PR("AMPDUs Completed:", a_completed);
+ PR("AMPDUs Retried: ", a_retries);
+ PR("AMPDUs XRetried: ", a_xretries);
+ PR("FIFO Underrun: ", fifo_underrun);
+ PR("TXOP Exceeded: ", xtxop);
+ PR("TXTIMER Expiry: ", timer_exp);
+ PR("DESC CFG Error: ", desc_cfg_err);
+ PR("DATA Underrun: ", data_underrun);
+ PR("DELIM Underrun: ", delim_underrun);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf)
+{
+ struct ath_desc *ds = bf->bf_desc;
+
+ if (bf_isampdu(bf)) {
+ if (bf_isxretried(bf))
+ TX_STAT_INC(txq->axq_qnum, a_xretries);
+ else
+ TX_STAT_INC(txq->axq_qnum, a_completed);
+ } else {
+ TX_STAT_INC(txq->axq_qnum, completed);
+ }
+
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_FIFO)
+ TX_STAT_INC(txq->axq_qnum, fifo_underrun);
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_XTXOP)
+ TX_STAT_INC(txq->axq_qnum, xtxop);
+ if (ds->ds_txstat.ts_status & ATH9K_TXERR_TIMER_EXPIRED)
+ TX_STAT_INC(txq->axq_qnum, timer_exp);
+ if (ds->ds_txstat.ts_flags & ATH9K_TX_DESC_CFG_ERR)
+ TX_STAT_INC(txq->axq_qnum, desc_cfg_err);
+ if (ds->ds_txstat.ts_flags & ATH9K_TX_DATA_UNDERRUN)
+ TX_STAT_INC(txq->axq_qnum, data_underrun);
+ if (ds->ds_txstat.ts_flags & ATH9K_TX_DELIM_UNDERRUN)
+ TX_STAT_INC(txq->axq_qnum, delim_underrun);
+}
+
+static const struct file_operations fops_xmit = {
+ .read = read_file_xmit,
+ .open = ath9k_debugfs_open,
+ .owner = THIS_MODULE
+};
int ath9k_init_debug(struct ath_softc *sc)
{
@@ -529,6 +606,13 @@ int ath9k_init_debug(struct ath_softc *sc)
if (!sc->debug.debugfs_wiphy)
goto err;
+ sc->debug.debugfs_xmit = debugfs_create_file("xmit",
+ S_IRUSR,
+ sc->debug.debugfs_phy,
+ sc, &fops_xmit);
+ if (!sc->debug.debugfs_xmit)
+ goto err;
+
return 0;
err:
ath9k_exit_debug(sc);
@@ -537,6 +621,7 @@ err:
void ath9k_exit_debug(struct ath_softc *sc)
{
+ debugfs_remove(sc->debug.debugfs_xmit);
debugfs_remove(sc->debug.debugfs_wiphy);
debugfs_remove(sc->debug.debugfs_rcstat);
debugfs_remove(sc->debug.debugfs_interrupt);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index edda15b..970951e 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -36,6 +36,12 @@ enum ATH_DEBUG {
#define DBG_DEFAULT (ATH_DBG_FATAL)
#ifdef CONFIG_ATH9K_DEBUG
+#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
+#else
+#define TX_STAT_INC(q, c) do { } while (0)
+#endif
+
+#ifdef CONFIG_ATH9K_DEBUG
/**
* struct ath_interrupt_stats - Contains statistics about interrupts
@@ -87,9 +93,45 @@ struct ath_rc_stats {
u8 per;
};
+/**
+ * struct ath_tx_stats - Statistics about TX
+ * @queued: Total MPDUs (non-aggr) queued
+ * @completed: Total MPDUs (non-aggr) completed
+ * @a_aggr: Total no. of aggregates queued
+ * @a_queued: Total AMPDUs queued
+ * @a_completed: Total AMPDUs completed
+ * @a_retries: No. of AMPDUs retried (SW)
+ * @a_xretries: No. of AMPDUs dropped due to xretries
+ * @fifo_underrun: FIFO underrun occurrences
+ Valid only for:
+ - non-aggregate condition.
+ - first packet of aggregate.
+ * @xtxop: No. of frames filtered because of TXOP limit
+ * @timer_exp: Transmit timer expiry
+ * @desc_cfg_err: Descriptor configuration errors
+ * @data_urn: TX data underrun errors
+ * @delim_urn: TX delimiter underrun errors
+ */
+struct ath_tx_stats {
+ u32 queued;
+ u32 completed;
+ u32 a_aggr;
+ u32 a_queued;
+ u32 a_completed;
+ u32 a_retries;
+ u32 a_xretries;
+ u32 fifo_underrun;
+ u32 xtxop;
+ u32 timer_exp;
+ u32 desc_cfg_err;
+ u32 data_underrun;
+ u32 delim_underrun;
+};
+
struct ath_stats {
struct ath_interrupt_stats istats;
struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
+ struct ath_tx_stats txstats[ATH9K_NUM_TX_QUEUES];
};
struct ath9k_debug {
@@ -100,9 +142,13 @@ struct ath9k_debug {
struct dentry *debugfs_interrupt;
struct dentry *debugfs_rcstat;
struct dentry *debugfs_wiphy;
+ struct dentry *debugfs_xmit;
struct ath_stats stats;
};
+struct ath_txq;
+struct ath_buf;
+
void DPRINTF(struct ath_softc *sc, int dbg_mask, const char *fmt, ...);
int ath9k_init_debug(struct ath_softc *sc);
void ath9k_exit_debug(struct ath_softc *sc);
@@ -110,6 +156,8 @@ int ath9k_debug_create_root(void);
void ath9k_debug_remove_root(void);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb);
+void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf);
void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per);
@@ -148,6 +196,12 @@ static inline void ath_debug_stat_rc(struct ath_softc *sc,
{
}
+static inline void ath_debug_stat_tx(struct ath_softc *sc,
+ struct ath_txq *txq,
+ struct ath_buf *bf)
+{
+}
+
static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
int xretries, int retries, u8 per)
{
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index c039d0a..8a8d7ed 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -59,6 +59,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
struct ath_atx_tid *tid,
struct list_head *bf_head);
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq,
struct list_head *bf_q,
int txok, int sendbar);
static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
@@ -212,7 +213,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_update_baw(sc, tid, bf->bf_seqno);
spin_unlock(&txq->axq_lock);
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
spin_lock(&txq->axq_lock);
}
@@ -220,13 +221,15 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq,
tid->baw_tail = tid->baw_head;
}
-static void ath_tx_set_retry(struct ath_softc *sc, struct ath_buf *bf)
+static void ath_tx_set_retry(struct ath_softc *sc, struct ath_txq *txq,
+ struct ath_buf *bf)
{
struct sk_buff *skb;
struct ieee80211_hdr *hdr;
bf->bf_state.bf_type |= BUF_RETRY;
bf->bf_retries++;
+ TX_STAT_INC(txq->axq_qnum, a_retries);
skb = bf->bf_mpdu;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -328,7 +331,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
if (!(tid->state & AGGR_CLEANUP) &&
ds->ds_txstat.ts_flags != ATH9K_TX_SW_ABORTED) {
if (bf->bf_retries < ATH_MAX_SW_RETRIES) {
- ath_tx_set_retry(sc, bf);
+ ath_tx_set_retry(sc, txq, bf);
txpending = 1;
} else {
bf->bf_state.bf_type |= BUF_XRETRY;
@@ -375,7 +378,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
ath_tx_rc_status(bf, ds, nbad, txok, false);
}
- ath_tx_complete_buf(sc, bf, &bf_head, !txfail, sendbar);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, !txfail, sendbar);
} else {
/* retry the un-acked ones */
if (bf->bf_next == NULL && bf_last->bf_stale) {
@@ -395,8 +398,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_state.bf_type |= BUF_XRETRY;
ath_tx_rc_status(bf, ds, nbad,
0, false);
- ath_tx_complete_buf(sc, bf, &bf_head,
- 0, 0);
+ ath_tx_complete_buf(sc, bf, txq,
+ &bf_head, 0, 0);
break;
}
@@ -573,6 +576,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
}
static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
+ struct ath_txq *txq,
struct ath_atx_tid *tid,
struct list_head *bf_q)
{
@@ -637,6 +641,7 @@ static enum ATH_AGGR_STATUS ath_tx_form_aggr(struct ath_softc *sc,
bf_prev->bf_desc->ds_link = bf->bf_daddr;
}
bf_prev = bf;
+
} while (!list_empty(&tid->buf_q));
bf_first->bf_al = al;
@@ -659,7 +664,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
INIT_LIST_HEAD(&bf_q);
- status = ath_tx_form_aggr(sc, tid, &bf_q);
+ status = ath_tx_form_aggr(sc, txq, tid, &bf_q);
/*
* no frames picked up to be aggregated;
@@ -690,6 +695,7 @@ static void ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq,
txq->axq_aggr_depth++;
ath_tx_txqaddbuf(sc, txq, &bf_q);
+ TX_STAT_INC(txq->axq_qnum, a_aggr);
} while (txq->axq_depth < ATH_AGGR_MIN_QDEPTH &&
status != ATH_AGGR_BAW_CLOSED);
@@ -746,7 +752,7 @@ int ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
}
list_move_tail(&bf->list, &bf_head);
ath_tx_update_baw(sc, txtid, bf->bf_seqno);
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
}
spin_unlock_bh(&txq->axq_lock);
@@ -870,7 +876,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
spin_lock_init(&txq->axq_lock);
txq->axq_depth = 0;
txq->axq_aggr_depth = 0;
- txq->axq_totalqueued = 0;
txq->axq_linkbuf = NULL;
txq->axq_tx_inprogress = false;
sc->tx.txqsetup |= 1<<qnum;
@@ -1036,7 +1041,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, 0);
else
- ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, 0, 0);
}
spin_lock_bh(&txq->axq_lock);
@@ -1187,7 +1192,6 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
list_splice_tail_init(head, &txq->axq_q);
txq->axq_depth++;
- txq->axq_totalqueued++;
txq->axq_linkbuf = list_entry(txq->axq_q.prev, struct ath_buf, list);
DPRINTF(sc, ATH_DBG_QUEUE,
@@ -1235,6 +1239,7 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
bf = list_first_entry(bf_head, struct ath_buf, list);
bf->bf_state.bf_type |= BUF_AMPDU;
+ TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
/*
* Do not queue to h/w when any of the following conditions is true:
@@ -1281,6 +1286,7 @@ static void ath_tx_send_ht_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_lastbf = bf;
ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head);
+ TX_STAT_INC(txq->axq_qnum, queued);
}
static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
@@ -1294,6 +1300,7 @@ static void ath_tx_send_normal(struct ath_softc *sc, struct ath_txq *txq,
bf->bf_nframes = 1;
ath_buf_set_rate(sc, bf);
ath_tx_txqaddbuf(sc, txq, bf_head);
+ TX_STAT_INC(txq->axq_qnum, queued);
}
static enum ath9k_pkt_type get_hw_packet_type(struct sk_buff *skb)
@@ -1819,6 +1826,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
}
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
+ struct ath_txq *txq,
struct list_head *bf_q,
int txok, int sendbar)
{
@@ -1826,7 +1834,6 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
unsigned long flags;
int tx_flags = 0;
-
if (sendbar)
tx_flags = ATH_TX_BAR;
@@ -1839,6 +1846,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
dma_unmap_single(sc->dev, bf->bf_dmacontext, skb->len, DMA_TO_DEVICE);
ath_tx_complete(sc, skb, tx_flags);
+ ath_debug_stat_tx(sc, txq, bf);
/*
* Return the list of ath_buf of this mpdu to free queue
@@ -2026,7 +2034,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
if (bf_isampdu(bf))
ath_tx_complete_aggr(sc, txq, bf, &bf_head, txok);
else
- ath_tx_complete_buf(sc, bf, &bf_head, txok, 0);
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, txok, 0);
ath_wake_mac80211_queue(sc, txq);
--
1.6.3.3
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox