Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] mac80211: remove useless work starting
From: Johannes Berg @ 2010-05-28 12:48 UTC (permalink / raw)
  To: John Linville; +Cc: linux-wireless

Ever since we use only cfg80211 for configuration,
there is no configuration that could be pending at
this point, cfg80211 will have the configuration
that is pending and apply it afterwards.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
---
 net/mac80211/iface.c |    9 ---------
 1 file changed, 9 deletions(-)

--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 14:47:29.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 14:47:32.000000000 +0200
@@ -321,15 +321,6 @@ static int ieee80211_open(struct net_dev
 
 	ieee80211_recalc_ps(local, -1);
 
-	/*
-	 * ieee80211_sta_work is disabled while network interface
-	 * is down. Therefore, some configuration changes may not
-	 * yet be effective. Trigger execution of ieee80211_sta_work
-	 * to fix this.
-	 */
-	if (sdata->vif.type == NL80211_IFTYPE_STATION)
-		ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
-
 	netif_tx_start_all_queues(dev);
 
 	return 0;



^ permalink raw reply

* [PATCH] mac80211: process station blockack action frames from work
From: Johannes Berg @ 2010-05-28 13:22 UTC (permalink / raw)
  To: linux-wireless; +Cc: Reinette Chatre, John Linville, Zhu Yi

From: Johannes Berg <johannes.berg@intel.com>

Processing an association response could take a bit
of time while we set up the hardware etc. During that
time, the AP might already send a blockack request.
If this happens very quickly on a fairly slow machine,
we can end up processing the blockack request before
the association processing has finished. Since the
blockack processing cannot sleep right now, we also
cannot make it wait in the driver.

As a result, sometimes on slow machines the iwlagn
driver gets totally confused, and no traffic can pass
when the aggregation setup was done before the assoc
setup completed.

I'm working on a proper fix for this, which involves
queuing all blockack category action frames from a
work struct, and also allowing the ampdu_action driver
callback to sleep, which will generally clean up the
code and make things easier.

However, this is a very involved and complex change.
To fix the problem at hand in a way that can also be
backported to stable, I've come up with this patch.
Here, I simply process all aggregation action frames
from the managed interface skb queue, which means
their processing will be serialized with processing
the association response, thereby fixing the problem.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Cc: stable@kernel.org
---
 net/mac80211/mlme.c |   52 +++++++++++++++++++++++++++++++++++++++++++++-------
 net/mac80211/rx.c   |    3 +++
 2 files changed, 48 insertions(+), 7 deletions(-)

--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 15:10:29.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 15:12:04.000000000 +0200
@@ -1692,14 +1692,52 @@ static void ieee80211_sta_rx_queued_mgmt
 			rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
 			break;
 		case IEEE80211_STYPE_ACTION:
-			if (mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
-				break;
+			switch (mgmt->u.action.category) {
+			case WLAN_CATEGORY_BACK: {
+				struct ieee80211_local *local = sdata->local;
+				int len = skb->len;
+				struct sta_info *sta;
 
-			ieee80211_sta_process_chanswitch(sdata,
-					&mgmt->u.action.u.chan_switch.sw_elem,
-					(void *)ifmgd->associated->priv,
-					rx_status->mactime);
-			break;
+				rcu_read_lock();
+				sta = sta_info_get(sdata, mgmt->sa);
+				if (!sta) {
+					rcu_read_unlock();
+					break;
+				}
+
+				local_bh_disable();
+
+				switch (mgmt->u.action.u.addba_req.action_code) {
+				case WLAN_ACTION_ADDBA_REQ:
+					if (len < (IEEE80211_MIN_ACTION_SIZE +
+						   sizeof(mgmt->u.action.u.addba_req)))
+						break;
+					ieee80211_process_addba_request(local, sta, mgmt, len);
+					break;
+				case WLAN_ACTION_ADDBA_RESP:
+					if (len < (IEEE80211_MIN_ACTION_SIZE +
+						   sizeof(mgmt->u.action.u.addba_resp)))
+						break;
+					ieee80211_process_addba_resp(local, sta, mgmt, len);
+					break;
+				case WLAN_ACTION_DELBA:
+					if (len < (IEEE80211_MIN_ACTION_SIZE +
+						   sizeof(mgmt->u.action.u.delba)))
+						break;
+					ieee80211_process_delba(sdata, sta, mgmt, len);
+					break;
+				}
+				local_bh_enable();
+				rcu_read_unlock();
+				break;
+				}
+			case WLAN_CATEGORY_SPECTRUM_MGMT:
+				ieee80211_sta_process_chanswitch(sdata,
+						&mgmt->u.action.u.chan_switch.sw_elem,
+						(void *)ifmgd->associated->priv,
+						rx_status->mactime);
+				break;
+			}
 		}
 		mutex_unlock(&ifmgd->mtx);
 
--- wireless-testing.orig/net/mac80211/rx.c	2010-05-28 14:22:59.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c	2010-05-28 15:11:47.000000000 +0200
@@ -1936,6 +1936,9 @@ ieee80211_rx_h_action(struct ieee80211_r
 		if (len < IEEE80211_MIN_ACTION_SIZE + 1)
 			break;
 
+		if (sdata->vif.type == NL80211_IFTYPE_STATION)
+			return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+
 		switch (mgmt->u.action.u.addba_req.action_code) {
 		case WLAN_ACTION_ADDBA_REQ:
 			if (len < (IEEE80211_MIN_ACTION_SIZE +



^ permalink raw reply

* MDNS is broken in latest -git
From: Maxim Levitsky @ 2010-05-28 15:02 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: linux-wireless

On latest git, it became impossible to use hostname.local alias to
access my network hosts.

In fact when I look at 'avahi-discover' I see nothing but local
services.

I did a bisect, but unfortunely ended with merge commit, although
bisection seem to be normal (and I didn't do any shortcuts).

I own a iwl3945 wireless card.


The bisection log:

git bisect start
# good: [537b60d17894b7c19a6060feae40299d7109d6e7] Merge branch 'x86-uv-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
git bisect good 537b60d17894b7c19a6060feae40299d7109d6e7
# bad: [d515e86e639890b33a09390d062b0831664f04a2] Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-udf-2.6
git bisect bad d515e86e639890b33a09390d062b0831664f04a2
# good: [a26272e5200765691e67d6780e52b32498fdb659] Merge branch 'docs-next' of git://git.lwn.net/linux-2.6
git bisect good a26272e5200765691e67d6780e52b32498fdb659
# good: [10fc51b9953112ade61e33ff2f6f005f005a2361] skge: use the DMA state API instead of the pci equivalents
git bisect good 10fc51b9953112ade61e33ff2f6f005f005a2361
# bad: [c316ba3b518bc35ce5aef5421135220389f4eb98] Merge branch 'linux-next' of git://git.infradead.org/ubi-2.6
git bisect bad c316ba3b518bc35ce5aef5421135220389f4eb98
# bad: [7a9b149212f3716c598afe973b6261fd58453b7a] Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
git bisect bad 7a9b149212f3716c598afe973b6261fd58453b7a
# good: [726ef428af41b1fbdf569772ab73de0844c4e0f2] USB: belkin_sa: minor clean-ups
git bisect good 726ef428af41b1fbdf569772ab73de0844c4e0f2
# good: [6fe70aae0d128339febfabc073ba4c4a03de4f45] Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
git bisect good 6fe70aae0d128339febfabc073ba4c4a03de4f45
# bad: [57b610805ce92dbd79fc97509f80fa5391b99623] net: Add netlink support for virtual port management (was iovnl)
git bisect bad 57b610805ce92dbd79fc97509f80fa5391b99623
# good: [78ad38923094a479453f5b02b37a012377a36f34] qlcnic: fix internal loopback test
git bisect good 78ad38923094a479453f5b02b37a012377a36f34
# good: [e1bc7eedbafe0415cdfd82e17e6f65bb3369239d] atm: select FW_LOADER in Kconfig for solos-pci
git bisect good e1bc7eedbafe0415cdfd82e17e6f65bb3369239d
# bad: [eedf042a63ffef050ebc015de19b52dc065e830b] ipv6: fix the bug of address check
git bisect bad eedf042a63ffef050ebc015de19b52dc065e830b
# good: [99bf236612801351834b441314379bc5304d62ce] drivers/net/usb: Use kmemdup
git bisect good 99bf236612801351834b441314379bc5304d62ce
# good: [380fefb2ddabd4cd5f14dbe090481f0544e65078] dm9000: fix "BUG: spinlock recursion"
git bisect good 380fefb2ddabd4cd5f14dbe090481f0544e65078
# bad: [820ae8a80eb59962aefbbd4908dfe144ec0f9edb] Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
git bisect bad 820ae8a80eb59962aefbbd4908dfe144ec0f9edb



^ permalink raw reply

* Re: Iwlwifi and LEDS?
From: Richard Purdie @ 2010-05-28 14:58 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Gregy, reinette chatre, linux-wireless@vger.kernel.org,
	Richard Purdie
In-Reply-To: <1275045779.3909.90.camel@jlt3.sipsolutions.net>

On Fri, 2010-05-28 at 13:22 +0200, Johannes Berg wrote:
> Richard, please see below after the *** -- I have a question for you.
> 
> On Fri, 2010-05-28 at 13:01 +0200, Gregy wrote:
> > > If you want to be able to manipulate the LED in other ways than the
> > > driver supports you could look into adding a debugfs file that
> > > manipulates the driver's led variables (allow_blinking,
> > > last_blink_time, ...). There is already a readable led file in debugfs,
> > > but not writable.
> > >
> > > Reinette
> > 
> > Ok, I have tried that with partial success. It allows me to change led
> > status "mid-flight" but if led is blinking it sometimes works only
> > after second try. Also my understanding of C and kernel programming is
> > very limited so I probably made some mistakes. Could you please look
> > at it?
> 
> I don't think this is the correct approach. I guess since the patch you
> referenced is mine, I should comment.
> 
> Prior to my patch, iwlwifi would register LEDs in the LED subsystem, but
> it didn't really properly do that since a lot of internal code just
> updates the LEDs. Additionally, by default the requirement is that the
> LED blinks according to traffic. Also, the blinking itself is done by
> the device, it is not done by the host CPU.
> 
> At the time of the patch, the LED subsystem didn't support blinking.
> This has changed now, I think, but previously it was not possible to set
> the LED to "blinking" like we need to have it. Additionally the LED
> trigger registration code that I removed was way more code for much less
> functionality than it should have been.
> 
> There's one proper way to fix this, but it is somewhat involved. Yes, I
> could have implemented that, but under the given time constraints, I
> opted for the cleanup that simply removed functionality that wasn't
> fully functional.
> 
> (*** mark for Richard)
> 
> The proper way to do this now would be to rewrite the LED code in
> iwlwifi to:
> 
> 1) register an LED again, which implements the blink_set() callback and
> programs the hw accordingly. This is essentially implementing
> iwl_led_pattern(), but with on_time/off_time parameters.
> 
> 2) Convert the current caller of iwl_led_pattern() to be an LED trigger
> that registers with the LED system. It would call the blink_set() for
> the LED it is connected to. Ideally, there should be some common
> software emulation if the LED has no blink_set(). Richard, is there a
> "make LED blink" callback that would start a timer for that LED? The
> timer trigger uses it but doesn't seem to be usable itself for other
> triggers?
> 
> 3) start the LED on device start, stop it on device stop
> 
> 4) depending on the module's led_mode, connect the LED to the
> appropriate default trigger, e.g. mac80211's assoc trigger or normally
> of course the new iwlwifi-blink trigger.

I have to admit I don't fully understand what the capabilities of your
hardware are.

Certainly registering a trigger with the LED system, maybe only
appearing for this specific hardware sounds like the way to go. Since
this will only appear as a trigger for this hardware, the trigger can
then poke whatever it needs into the hardware to work as a traffic
indication?

Cheers,

Richard




^ permalink raw reply

* Re: Iwlwifi and LEDS?
From: Johannes Berg @ 2010-05-28 15:08 UTC (permalink / raw)
  To: Richard Purdie
  Cc: Gregy, reinette chatre, linux-wireless@vger.kernel.org,
	Richard Purdie
In-Reply-To: <1275058729.24079.1488.camel@rex>

On Fri, 2010-05-28 at 15:58 +0100, Richard Purdie wrote:

> > The proper way to do this now would be to rewrite the LED code in
> > iwlwifi to:
> > 
> > 1) register an LED again, which implements the blink_set() callback and
> > programs the hw accordingly. This is essentially implementing
> > iwl_led_pattern(), but with on_time/off_time parameters.
> > 
> > 2) Convert the current caller of iwl_led_pattern() to be an LED trigger
> > that registers with the LED system. It would call the blink_set() for
> > the LED it is connected to. Ideally, there should be some common
> > software emulation if the LED has no blink_set(). Richard, is there a
> > "make LED blink" callback that would start a timer for that LED? The
> > timer trigger uses it but doesn't seem to be usable itself for other
> > triggers?
> > 
> > 3) start the LED on device start, stop it on device stop
> > 
> > 4) depending on the module's led_mode, connect the LED to the
> > appropriate default trigger, e.g. mac80211's assoc trigger or normally
> > of course the new iwlwifi-blink trigger.
> 
> I have to admit I don't fully understand what the capabilities of your
> hardware are.

Sorry, I didn't mean to confuse you with the hardware details. The
hardware can blink, essentially.

> Certainly registering a trigger with the LED system, maybe only
> appearing for this specific hardware sounds like the way to go. Since
> this will only appear as a trigger for this hardware, the trigger can
> then poke whatever it needs into the hardware to work as a traffic
> indication?

Yes, that would be one way. However, that would seem to unduly restrict
the trigger's use. It can be used with any LED that has a blink_set()
callback since it doesn't need to poke the hardware directly.

What I was wondering is if there is (or should be) a common "blink
emulation" for LEDs that don't have a blink_set, so instead of calling
	led->blink_set(...)
I would call
	led_blink_set(...)
and that would start the timer etc.

johannes


^ permalink raw reply

* Re: Problems connectring to an AP with Acer Aspire Revo
From: Carlos Balseiro @ 2010-05-28 15:48 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <AANLkTilrwpoTHSFBVBhGI0ZVJzX3EF49dypcQ4zUZsVB@mail.gmail.com>

I'm having exactly the same problem with the same hardware
combination. If I can help to diagnose the problem in any way just
tell me what to do.

^ permalink raw reply

* Re: [ath5k-devel] [PATCH] ath5k: disable ASPM
From: Pavel Roskin @ 2010-05-28 16:19 UTC (permalink / raw)
  To: Jussi Kivilinna; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <20100528100901.14580.1322.stgit@fate.lan>

On Fri, 2010-05-28 at 13:09 +0300, Jussi Kivilinna wrote:
> +static void		__ath5k_disable_aspm(struct pci_dev *pdev, u16 state);
> +static void		ath5k_disable_aspm(struct pci_dev *pdev, u16 state);

Forward declarations should not be needed unless the functions are
called before their implementations, which is not the case here.

> @@ -424,6 +427,47 @@ module_exit(exit_ath5k_pci);
>  * PCI Initialization *
>  \********************/
>  
> +#ifdef CONFIG_PCIEASPM
> +static void __ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
> +{
> +	pci_disable_link_state(pdev, state);
> +}
> +#else
> +static void __ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
> +{

It looks like a replacement for pci_disable_link_state() if
CONFIG_PCIEASPM is disabled.  I guess it should be in the PCI code, not
in ath5k.  At least the PCI developers should have a look at the
replacement code.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: Realtek rtl8188 support?
From: Pavel Roskin @ 2010-05-28 16:35 UTC (permalink / raw)
  To: Gábor Stefanik; +Cc: Paul Thomas, linux-wireless, Andrea Merello
In-Reply-To: <AANLkTin6cAHj2p266yMLQkrpkhCdX98leNl5F8f3DAJR@mail.gmail.com>

On Thu, 2010-05-27 at 00:21 +0200, Gábor Stefanik wrote:
> > But I cannot find the "r8192s_usb" symbol in any staging drivers, so I
> > have no idea which driver you are talking about.
> 
> r8192s_usb is not a symbol, it is the name of the module being loaded.

Oh, I see.  That means the driver is rtl8192su.  But its Kconfig file
already selects WIRELESS_EXT.  git log should that it was fixed by the
last commit to drivers/staging/rtl8192su/Kconfig:

commit 784d3119475652d34a8d8ec3911e39c5e3d3036f
Author: Simon Horman <horms@verge.net.au>
Date:   Mon Dec 21 15:07:10 2009 +1100

    Staging: rtl8192su: Build should select WIRELESS_EXT

As for the PCI dependency, it's probably wrong.  USB used to depend on
PCI, but I understand it's no longer true.

-- 
Regards,
Pavel Roskin

^ permalink raw reply

* Re: MDNS is broken in latest -git
From: Maxim Levitsky @ 2010-05-28 17:09 UTC (permalink / raw)
  To: netdev@vger.kernel.org; +Cc: linux-wireless
In-Reply-To: <1275058948.2754.7.camel@maxim-laptop>

On Fri, 2010-05-28 at 18:02 +0300, Maxim Levitsky wrote: 
> On latest git, it became impossible to use hostname.local alias to
> access my network hosts.
> 
> In fact when I look at 'avahi-discover' I see nothing but local
> services.
> 
> I did a bisect, but unfortunely ended with merge commit, although
> bisection seem to be normal (and I didn't do any shortcuts).

Since starting 'wireshark' magicly temporarly fixes this, I suspect that
mulicast packets don't get through.

This smells like iwl3945 bug.

I use linus' master tree now.

Best regards,
Maxim Levitsky


^ permalink raw reply

* Re: [PATCH] ath5k: disable ASPM
From: Luis R. Rodriguez @ 2010-05-28 17:40 UTC (permalink / raw)
  To: Jussi Kivilinna; +Cc: ath5k-devel, linux-wireless, David Quan
In-Reply-To: <20100528100901.14580.1322.stgit@fate.lan>

On Fri, May 28, 2010 at 3:09 AM, Jussi Kivilinna
<jussi.kivilinna@mbnet.fi> wrote:
> Atheros card on Acer Aspire One (AOA150, Atheros Communications Inc. AR5001
> Wireless Network Adapter [168c:001c] (rev 01)) doesn't work well with ASPM
> enabled. With ASPM ath5k will eventually stall on heavy traffic with often
> 'unsupported jumbo' warnings appearing. Disabling ASPM L0s/L1 in ath5k fixes
> these problems.

So you disable ASPM all together on the entire driver?

  Luis

> Reproduced with pcie_aspm=force and by using 'nc < /dev/zero > /dev/null' at
> both ends (usually stalls within seconds).
>
> Signed-off-by: Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
> ---
>  drivers/net/wireless/ath/ath5k/base.c |   48 +++++++++++++++++++++++++++++++++
>  1 files changed, 48 insertions(+), 0 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
> index cc6d41d..ce9c983 100644
> --- a/drivers/net/wireless/ath/ath5k/base.c
> +++ b/drivers/net/wireless/ath/ath5k/base.c
> @@ -48,6 +48,7 @@
>  #include <linux/netdevice.h>
>  #include <linux/cache.h>
>  #include <linux/pci.h>
> +#include <linux/pci-aspm.h>
>  #include <linux/ethtool.h>
>  #include <linux/uaccess.h>
>  #include <linux/slab.h>
> @@ -195,6 +196,8 @@ static const struct ieee80211_rate ath5k_rates[] = {
>  static int __devinit   ath5k_pci_probe(struct pci_dev *pdev,
>                                const struct pci_device_id *id);
>  static void __devexit  ath5k_pci_remove(struct pci_dev *pdev);
> +static void            __ath5k_disable_aspm(struct pci_dev *pdev, u16 state);
> +static void            ath5k_disable_aspm(struct pci_dev *pdev, u16 state);
>  #ifdef CONFIG_PM
>  static int             ath5k_pci_suspend(struct device *dev);
>  static int             ath5k_pci_resume(struct device *dev);
> @@ -424,6 +427,47 @@ module_exit(exit_ath5k_pci);
>  * PCI Initialization *
>  \********************/
>
> +#ifdef CONFIG_PCIEASPM
> +static void __ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
> +{
> +       pci_disable_link_state(pdev, state);
> +}
> +#else
> +static void __ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
> +{
> +       int pos;
> +       u16 reg16;
> +
> +       /*
> +        * Both device and parent should have the same ASPM setting.
> +        * Disable ASPM in downstream component first and then upstream.
> +        */
> +       pos = pci_pcie_cap(pdev);
> +       pci_read_config_word(pdev, pos + PCI_EXP_LNKCTL, &reg16);
> +       reg16 &= ~state;
> +       pci_write_config_word(pdev, pos + PCI_EXP_LNKCTL, reg16);
> +
> +       if (!pdev->bus->self)
> +               return;
> +
> +       pos = pci_pcie_cap(pdev->bus->self);
> +       pci_read_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, &reg16);
> +       reg16 &= ~state;
> +       pci_write_config_word(pdev->bus->self, pos + PCI_EXP_LNKCTL, reg16);
> +}
> +#endif
> +static void ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
> +{
> +       if (!pdev->is_pcie)
> +               return;
> +
> +       dev_info(&pdev->dev, "Disabling ASPM %s%s\n",
> +                (state & PCIE_LINK_STATE_L0S) ? "L0s " : "",
> +                (state & PCIE_LINK_STATE_L1) ? "L1" : "");
> +
> +       __ath5k_disable_aspm(pdev, state);
> +}
> +
>  static const char *
>  ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val)
>  {
> @@ -473,6 +517,8 @@ ath5k_pci_probe(struct pci_dev *pdev,
>        int ret;
>        u8 csz;
>
> +       ath5k_disable_aspm(pdev, PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_L0S);
> +
>        ret = pci_enable_device(pdev);
>        if (ret) {
>                dev_err(&pdev->dev, "can't enable device\n");
> @@ -725,6 +771,8 @@ static int ath5k_pci_resume(struct device *dev)
>        struct ieee80211_hw *hw = pci_get_drvdata(pdev);
>        struct ath5k_softc *sc = hw->priv;
>
> +       ath5k_disable_aspm(pdev, PCIE_LINK_STATE_L1 | PCIE_LINK_STATE_L0S);
> +
>        /*
>         * Suspend/Resume resets the PCI configuration space, so we have to
>         * re-disable the RETRY_TIMEOUT register (0x41) to keep
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply

* Re: new bluetooth id for lenovo T410s?
From: Luis R. Rodriguez @ 2010-05-28 17:42 UTC (permalink / raw)
  To: Martin Vogt; +Cc: linux-wireless
In-Reply-To: <4BFF9D8E.5040702@itwm.fraunhofer.de>

On Fri, May 28, 2010 at 3:40 AM, Martin Vogt
<martin.vogt@itwm.fraunhofer.de> wrote:
> Marcel Holtmann wrote:
>> Hi Martin,
>>
>> so first of all, this is the wrong mailing list. You should be using
>> linux-bluetooth@vger.kernel.org.
> Oh, ok.
>
>> Please send in the output of /proc/bus/usb/devices for your devices
>> since I doubt it is not supported. There are general interface
>> descriptors that make the devices work. Only if Lenovo screwed something
>> up, then this is needed.
>>
>
> Just a small update: It works now, the btusb driver
> from the compat-wireless module didnt load with symbol
> problems.
> (I use a Suse 2.6.27 vendor kernel which already is a bit 2.6.28+
> compat-wireless-2.6.34)
>
> I placed some #if 0 #endif combinations in compat-2.6.28.c
> ==>now it works.

Was this a Suse distribution problem? If so can you elaborate?

  Luis

^ permalink raw reply

* Re: [PATCH]: ath: Fix uninitialized variable warnings
From: John W. Linville @ 2010-05-28 17:34 UTC (permalink / raw)
  To: Prarit Bhargava; +Cc: linux-wireless, ath9k-devel
In-Reply-To: <20100527181052.23905.67123.sendpatchset@prarit.bos.redhat.com>

On Thu, May 27, 2010 at 02:14:54PM -0400, Prarit Bhargava wrote:
> Fixes 'make -j24 CONFIG_DEBUG_SECTION_MISMATCH=y' warning:
> 
> drivers/net/wireless/ath/ath9k/eeprom_4k.c: In function ‘ath9k_hw_get_4k_gain_boundaries_pdadcs.clone.1’:
> drivers/net/wireless/ath/ath9k/eeprom_4k.c:311: error: ‘minPwrT4’ may be used uninitialized in this function
> drivers/net/wireless/ath/ath9k/eeprom_9287.c: In function ‘ath9k_hw_get_AR9287_gain_boundaries_pdadcs’:
> drivers/net/wireless/ath/ath9k/eeprom_9287.c:302: error: ‘minPwrT4’ may be used uninitialized in this function
> drivers/net/wireless/ath/ath9k/eeprom_def.c: In function ‘ath9k_hw_get_def_gain_boundaries_pdadcs.clone.0’:
> drivers/net/wireless/ath/ath9k/eeprom_def.c:679: error: ‘minPwrT4’ may be used uninitialized in this function
> 
> Signed-off-by: Prarit Bhargava <prarit@redhat.com>

It looks to me like minPwrT4 will get initialized as long as
numXpdGains is non-zero in all cases.  Anyone know if this is true?

It's probably not a big deal, but better to avoid an unnecessary
memset if we can.  Maybe unitialized_var is the better choice?

John
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply

* pull request: wireless-2.6 2010-05-28
From: John W. Linville @ 2010-05-28 18:09 UTC (permalink / raw)
  To: davem; +Cc: linux-wireless, netdev, linux-kernel

Dave,

Here are a few small fixes intended for 2.6.35.  Included are a null
pointer dereference fix, and a use-after-free fix, as well as some more
minor stuff.  It also include the revert of a earlier patch that I
inadvertantly merged out of order, effectively creating a bug rather
than fixing one.  The reverted patch will now be pointed at 2.6.36
instead.

Please let me know if there are problems!

Thanks,

John

---

The following changes since commit 045de01a174d9f0734f657eb4b3313d89b4fd5ad:
  Scott Feldman (1):
        netlink: bug fix: wrong size was calculated for vfinfo list blob

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6.git master

Christian Lamparter (1):
      ar9170usb: fix read from freed driver context

Christoph Fritz (1):
      ssb: fix NULL ptr deref when pcihost_wrapper is used

Johannes Berg (1):
      mac80211: make a function static

John W. Linville (1):
      Revert "rt2x00: Fix rt2800usb TX descriptor writing."

Justin P. Mattock (1):
      ath9k: Fix ath_print in xmit for hardware reset.

Prarit Bhargava (1):
      libertas: fix uninitialized variable warning

Vasanthakumar Thiagarajan (1):
      ath9k: Fix bug in the way "bf_tx_aborted" of struct ath_buf is used

 drivers/net/wireless/ath/ar9170/usb.c   |   14 ++++++++++++--
 drivers/net/wireless/ath/ath9k/xmit.c   |    6 ++++--
 drivers/net/wireless/libertas/rx.c      |    5 ++---
 drivers/net/wireless/rt2x00/rt2800usb.c |    2 +-
 drivers/ssb/pci.c                       |    9 ++++++---
 drivers/ssb/sprom.c                     |    1 +
 net/mac80211/chan.c                     |    2 +-
 7 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/drivers/net/wireless/ath/ar9170/usb.c b/drivers/net/wireless/ath/ar9170/usb.c
index 82ab532..a93dc18 100644
--- a/drivers/net/wireless/ath/ar9170/usb.c
+++ b/drivers/net/wireless/ath/ar9170/usb.c
@@ -739,17 +739,27 @@ err_out:
 static void ar9170_usb_firmware_failed(struct ar9170_usb *aru)
 {
 	struct device *parent = aru->udev->dev.parent;
+	struct usb_device *udev;
+
+	/*
+	 * Store a copy of the usb_device pointer locally.
+	 * This is because device_release_driver initiates
+	 * ar9170_usb_disconnect, which in turn frees our
+	 * driver context (aru).
+	 */
+	udev = aru->udev;
 
 	complete(&aru->firmware_loading_complete);
 
 	/* unbind anything failed */
 	if (parent)
 		device_lock(parent);
-	device_release_driver(&aru->udev->dev);
+
+	device_release_driver(&udev->dev);
 	if (parent)
 		device_unlock(parent);
 
-	usb_put_dev(aru->udev);
+	usb_put_dev(udev);
 }
 
 static void ar9170_usb_firmware_finish(const struct firmware *fw, void *context)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 3db1917..859aa4a 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1198,7 +1198,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
 		int r;
 
 		ath_print(common, ATH_DBG_FATAL,
-			  "Unable to stop TxDMA. Reset HAL!\n");
+			  "Failed to stop TX DMA. Resetting hardware!\n");
 
 		spin_lock_bh(&sc->sc_resetlock);
 		r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false);
@@ -1728,6 +1728,8 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
 	} else
 		bf->bf_isnullfunc = false;
 
+	bf->bf_tx_aborted = false;
+
 	return 0;
 }
 
@@ -1989,7 +1991,7 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
 	int nbad = 0;
 	int isaggr = 0;
 
-	if (bf->bf_tx_aborted)
+	if (bf->bf_lastbf->bf_tx_aborted)
 		return 0;
 
 	isaggr = bf_isaggr(bf);
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index a115bfa..7a377f5 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -329,9 +329,8 @@ static int process_rxed_802_11_packet(struct lbs_private *priv,
 	/* create the exported radio header */
 
 	/* radiotap header */
-	radiotap_hdr.hdr.it_version = 0;
-	/* XXX must check this value for pad */
-	radiotap_hdr.hdr.it_pad = 0;
+	memset(&radiotap_hdr, 0, sizeof(radiotap_hdr));
+	/* XXX must check radiotap_hdr.hdr.it_pad for pad */
 	radiotap_hdr.hdr.it_len = cpu_to_le16 (sizeof(struct rx_radiotap_hdr));
 	radiotap_hdr.hdr.it_present = cpu_to_le32 (RX_RADIOTAP_PRESENT);
 	radiotap_hdr.rate = convert_mv_rate_to_radiotap(prxpd->rx_rate);
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 6991613..0f8b84b 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -413,7 +413,7 @@ static void rt2800usb_write_tx_desc(struct rt2x00_dev *rt2x00dev,
 	 */
 	rt2x00_desc_read(txi, 0, &word);
 	rt2x00_set_field32(&word, TXINFO_W0_USB_DMA_TX_PKT_LEN,
-			   skb->len - TXINFO_DESC_SIZE);
+			   skb->len + TXWI_DESC_SIZE);
 	rt2x00_set_field32(&word, TXINFO_W0_WIV,
 			   !test_bit(ENTRY_TXD_ENCRYPT_IV, &txdesc->flags));
 	rt2x00_set_field32(&word, TXINFO_W0_QSEL, 2);
diff --git a/drivers/ssb/pci.c b/drivers/ssb/pci.c
index 989e275..6dcda86 100644
--- a/drivers/ssb/pci.c
+++ b/drivers/ssb/pci.c
@@ -625,9 +625,12 @@ static int ssb_pci_sprom_get(struct ssb_bus *bus,
 		ssb_printk(KERN_ERR PFX "No SPROM available!\n");
 		return -ENODEV;
 	}
-
-	bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
-		SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+	if (bus->chipco.dev) {	/* can be unavailible! */
+		bus->sprom_offset = (bus->chipco.dev->id.revision < 31) ?
+			SSB_SPROM_BASE1 : SSB_SPROM_BASE31;
+	} else {
+		bus->sprom_offset = SSB_SPROM_BASE1;
+	}
 
 	buf = kcalloc(SSB_SPROMSIZE_WORDS_R123, sizeof(u16), GFP_KERNEL);
 	if (!buf)
diff --git a/drivers/ssb/sprom.c b/drivers/ssb/sprom.c
index 007bc3a..4f7cc8d 100644
--- a/drivers/ssb/sprom.c
+++ b/drivers/ssb/sprom.c
@@ -185,6 +185,7 @@ bool ssb_is_sprom_available(struct ssb_bus *bus)
 	/* this routine differs from specs as we do not access SPROM directly
 	   on PCMCIA */
 	if (bus->bustype == SSB_BUSTYPE_PCI &&
+	    bus->chipco.dev &&	/* can be unavailible! */
 	    bus->chipco.dev->id.revision >= 31)
 		return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
 
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5d218c5..32be11e 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -5,7 +5,7 @@
 #include <linux/nl80211.h>
 #include "ieee80211_i.h"
 
-enum ieee80211_chan_mode
+static enum ieee80211_chan_mode
 __ieee80211_get_channel_mode(struct ieee80211_local *local,
 			     struct ieee80211_sub_if_data *ignore)
 {
-- 
John W. Linville		Someday the world will need a hero, and you
linville@tuxdriver.com			might be all we have.  Be ready.

^ permalink raw reply related

* Re: ath5k past 2.6.30 breaks monitor mode (and thus the aircrack suite)
From: Richard Farina @ 2010-05-28 18:16 UTC (permalink / raw)
  To: Bob Copeland; +Cc: Gábor Stefanik, Weedy, linux-wireless, Johannes Berg
In-Reply-To: <AANLkTin3VSp_FcSiadD4efE1Yo1vKiDXmOngsHEKiQmF@mail.gmail.com>

Bob Copeland wrote:
> On Wed, May 26, 2010 at 11:49 PM, Richard Farina <sidhayn@gmail.com> wrote:
>   
>> Bob Copeland wrote:
>>     
>>> Ok, it should be enough to look at the filter flags instead of
>>> the opmode -- I knew in the back of my mind that the monitor
>>> stuff was bogus (part of the reason I did the patch in the first
>>> place) but just got confused by what was already there I guess.
>>>       
>> I've got a lot of people very interested in this fix. Let me know what kind
>> of support you need to make this happen.  You know where to find me on irc
>> ;-)
>>     
>
> Ok, can you and Weedy try this patch?
>
> Use the attachment -- gmail will screw up the whitespace, but I included
> it inline for reference.
>
> Weedy, if you want reported-by credit can you give your full name and
> preferred email address?
>
> From: Bob Copeland <me@bobcopeland.com>
> Date: Thu, 27 May 2010 08:54:38 -0400
> Subject: [PATCH] ath5k: retain promiscuous setting
>
> Commit 56d1de0a21db28e41741cfa0a66e18bc8d920554, "ath5k: clean up
> filter flags setting" introduced a regression in monitor mode such
> that the promisc filter flag would get lost.
>
> Although we set the promisc flag when it changed, we did not
> preserve it across subsequent calls to configure_filter.  This patch
> restores the original functionality.
>
> Cc: stable@kernel.org
> Signed-off-by: Bob Copeland <me@bobcopeland.com>
> ---
>
> Note, a better fix would be to just unconditionally look at new_flags,
> but this is the minimal change for stable.  I'll add fixing all this
> stuff up to my todo.
>
>  drivers/net/wireless/ath/ath5k/base.c |    4 +++-
>  1 files changed, 3 insertions(+), 1 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath5k/base.c
> b/drivers/net/wireless/ath/ath5k/base.c
> index 9c27623..9e023b8 100644
> --- a/drivers/net/wireless/ath/ath5k/base.c
> +++ b/drivers/net/wireless/ath/ath5k/base.c
> @@ -3153,13 +3153,15 @@ static void ath5k_configure_filter(struct
> ieee80211_hw *hw,
>
>  	if (changed_flags & (FIF_PROMISC_IN_BSS | FIF_OTHER_BSS)) {
>  		if (*new_flags & FIF_PROMISC_IN_BSS) {
> -			rfilt |= AR5K_RX_FILTER_PROM;
>  			__set_bit(ATH_STAT_PROMISC, sc->status);
>  		} else {
>  			__clear_bit(ATH_STAT_PROMISC, sc->status);
>  		}
>  	}
>
> +	if (test_bit(ATH_STAT_PROMISC, sc->status))
> +		rfilt |= AR5K_RX_FILTER_PROM;
> +
>  	/* Note, AR5K_RX_FILTER_MCAST is already enabled */
>  	if (*new_flags & FIF_ALLMULTI) {
>  		mfilt[0] =  ~0;
>   
Tested-By: Rick Farina

This patch fixes the problem, data packets are now captured while in 
monitor mode.  Incidentally when I tried to chase this back to see when 
it started I found the same behavior in 2.6.32_rc and even in 2.6.29 
(which is funny since Weedy bisected the change to some time during 
2.6.31_rc5).  This fix should be pushed out to as much of stable as 
possible as soon as possible.  Thanks for the patch Bob!

-Rick Farina

^ permalink raw reply

* Re: [PATCH] ath5k: disable ASPM
From: Jussi Kivilinna @ 2010-05-28 18:20 UTC (permalink / raw)
  To: Luis R. Rodriguez; +Cc: ath5k-devel, linux-wireless, David Quan
In-Reply-To: <AANLkTim27Widx4NuaN_C6XqeLkCahRA8zTEDuDtxi_vM@mail.gmail.com>

Quoting "Luis R. Rodriguez" <mcgrof@gmail.com>:

> On Fri, May 28, 2010 at 3:09 AM, Jussi Kivilinna
> <jussi.kivilinna@mbnet.fi> wrote:
>> Atheros card on Acer Aspire One (AOA150, Atheros Communications Inc. AR5001
>> Wireless Network Adapter [168c:001c] (rev 01)) doesn't work well with ASPM
>> enabled. With ASPM ath5k will eventually stall on heavy traffic with often
>> 'unsupported jumbo' warnings appearing. Disabling ASPM L0s/L1 in ath5k fixes
>> these problems.
>
> So you disable ASPM all together on the entire driver?
>

Sorry, I meant to this to be RFC patch. I'm not familiar with PCI  
devices/drivers.. How should I pinpoint this patch? To 168c:001c? only  
rev 1? Is there other revs that don't mix with ASPM? Is this AOA150  
problem only? Use AOA150 specific quirk?

-Jussi


^ permalink raw reply

* Re: [ath5k-devel] [PATCH] ath5k: disable ASPM
From: Jussi Kivilinna @ 2010-05-28 18:25 UTC (permalink / raw)
  To: Pavel Roskin; +Cc: ath5k-devel, linux-wireless
In-Reply-To: <1275063576.15168.14.camel@mj>

Quoting "Pavel Roskin" <proski@gnu.org>:

> On Fri, 2010-05-28 at 13:09 +0300, Jussi Kivilinna wrote:
>> +static void		__ath5k_disable_aspm(struct pci_dev *pdev, u16 state);
>> +static void		ath5k_disable_aspm(struct pci_dev *pdev, u16 state);
>
> Forward declarations should not be needed unless the functions are
> called before their implementations, which is not the case here.

Ok.

>
>> @@ -424,6 +427,47 @@ module_exit(exit_ath5k_pci);
>>  * PCI Initialization *
>>  \********************/
>>
>> +#ifdef CONFIG_PCIEASPM
>> +static void __ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
>> +{
>> +	pci_disable_link_state(pdev, state);
>> +}
>> +#else
>> +static void __ath5k_disable_aspm(struct pci_dev *pdev, u16 state)
>> +{
>
> It looks like a replacement for pci_disable_link_state() if
> CONFIG_PCIEASPM is disabled.  I guess it should be in the PCI code, not
> in ath5k.  At least the PCI developers should have a look at the
> replacement code.

I used code from e1000e which does this same way, which now suddenly  
reminds me of that ath5k is dual lisenced, right? Can I even reuse  
code from GPL driver in ath5k?

-Jussi


^ permalink raw reply

* Re: Path for fixed channel issue in aircrack-ng suite
From: Richard Farina @ 2010-05-28 18:28 UTC (permalink / raw)
  To: Johannes Berg; +Cc: Gábor Stefanik, Joker Joker, linux-wireless
In-Reply-To: <1274860275.3658.0.camel@jlt3.sipsolutions.net>

Johannes Berg wrote:
> On Wed, 2010-05-26 at 00:54 +0200, Gábor Stefanik wrote:
>
>   
>>>> -       if (wdev)
>>>> -               wdev->channel = chan;
>>>> +       wdev = old_wdev;
>>>> +       wdev->channel = chan;
>>>>         
>>> NACK. That will crash when there really is no interface being passed in.
>>>
>>> johannes
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
>>> the body of a message to majordomo@vger.kernel.org
>>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>>
>>>       
>> Well, the original version already dereferences wdev in "if
>> (wdev->iftype...", so the crash is nothing new if it exists.
>>     
>
> It has also been fixed since.
>
>   
Is someone porting this fix into wireless-testing and stable or does 
that still need to be done? Fixed channel of -1 is sort of an issue for 
using monitor mode....

Thanks,
Rick
> johannes
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>   


^ permalink raw reply

* [RFC 0/7] mac80211: preparations for blocking ampdu_action
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless

Hi all,

These are some preparatory and cleanup patches
for a blocking ampdu_action callback that will
allow simplified locking in drivers and avoid
the race condition I had pointed out and posted
a workaround for around earlier.

Obviously, the interesting patch that actually
does that is still missing, but I wanted to
have people review these patches first anyway
since they can stand on their own and smaller
patch batches are always good :)

johannes


^ permalink raw reply

* [RFC 1/7] mac80211: simplify station/aggregation code
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

A number of places use RCU locking for accessing
the station list, even though they do not need
to. Use mutex locking instead to prepare for the
locking changes I want to make.

While doing so, combine places where we loop
over stations twice, and optimise away some of
the loops by checking if the hardware supports
aggregation at all first.

Also fix a more theoretical race condition: right
now we could resume, set up an aggregation session,
and right after tear it down again due to the code
that is needed for hardware reconfiguration here.
Also mark add a comment to that code marking it as
a workaround.

Finally, remove a pointless aggregation disabling
loop when an interface is stopped, directly after
that we remove all stations from it which will also
disable all aggregation sessions that may still be
active, and does so in a race-free way unlike the
current loop that doesn't block new sessions.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/iface.c |   13 -------------
 net/mac80211/pm.c    |   16 ++++------------
 net/mac80211/util.c  |   31 ++++++++++++++++---------------
 3 files changed, 20 insertions(+), 40 deletions(-)

--- wireless-testing.orig/net/mac80211/pm.c	2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/pm.c	2010-05-28 20:36:01.000000000 +0200
@@ -40,22 +40,14 @@ int __ieee80211_suspend(struct ieee80211
 	list_for_each_entry(sdata, &local->interfaces, list)
 		ieee80211_disable_keys(sdata);
 
-	/* Tear down aggregation sessions */
-
-	rcu_read_lock();
-
-	if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
-		list_for_each_entry_rcu(sta, &local->sta_list, list) {
+	/* tear down aggregation sessions and remove STAs */
+	mutex_lock(&local->sta_mtx);
+	list_for_each_entry(sta, &local->sta_list, list) {
+		if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
 			set_sta_flags(sta, WLAN_STA_BLOCK_BA);
 			ieee80211_sta_tear_down_BA_sessions(sta);
 		}
-	}
 
-	rcu_read_unlock();
-
-	/* remove STAs */
-	mutex_lock(&local->sta_mtx);
-	list_for_each_entry(sta, &local->sta_list, list) {
 		if (sta->uploaded) {
 			sdata = sta->sdata;
 			if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
--- wireless-testing.orig/net/mac80211/util.c	2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/util.c	2010-05-28 20:36:01.000000000 +0200
@@ -1138,18 +1138,6 @@ int ieee80211_reconfig(struct ieee80211_
 	}
 	mutex_unlock(&local->sta_mtx);
 
-	/* Clear Suspend state so that ADDBA requests can be processed */
-
-	rcu_read_lock();
-
-	if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
-		list_for_each_entry_rcu(sta, &local->sta_list, list) {
-			clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
-		}
-	}
-
-	rcu_read_unlock();
-
 	/* setup RTS threshold */
 	drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
 
@@ -1202,13 +1190,26 @@ int ieee80211_reconfig(struct ieee80211_
 		}
 	}
 
-	rcu_read_lock();
+	/*
+	 * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
+	 * sessions can be established after a resume.
+	 *
+	 * Also tear down aggregation sessions since reconfiguring
+	 * them in a hardware restart scenario is not easily done
+	 * right now, and the hardware will have lost information
+	 * about the sessions, but we and the AP still think they
+	 * are active. This is really a workaround though.
+	 */
 	if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
-		list_for_each_entry_rcu(sta, &local->sta_list, list) {
+		mutex_lock(&local->sta_mtx);
+
+		list_for_each_entry(sta, &local->sta_list, list) {
 			ieee80211_sta_tear_down_BA_sessions(sta);
+			clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
 		}
+
+		mutex_unlock(&local->sta_mtx);
 	}
-	rcu_read_unlock();
 
 	/* add back keys */
 	list_for_each_entry(sdata, &local->interfaces, list)
--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 20:36:01.000000000 +0200
@@ -340,7 +340,6 @@ static int ieee80211_stop(struct net_dev
 {
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 	struct ieee80211_local *local = sdata->local;
-	struct sta_info *sta;
 	unsigned long flags;
 	struct sk_buff *skb, *tmp;
 	u32 hw_reconf_flags = 0;
@@ -357,18 +356,6 @@ static int ieee80211_stop(struct net_dev
 	ieee80211_work_purge(sdata);
 
 	/*
-	 * Now delete all active aggregation sessions.
-	 */
-	rcu_read_lock();
-
-	list_for_each_entry_rcu(sta, &local->sta_list, list) {
-		if (sta->sdata == sdata)
-			ieee80211_sta_tear_down_BA_sessions(sta);
-	}
-
-	rcu_read_unlock();
-
-	/*
 	 * Remove all stations associated with this interface.
 	 *
 	 * This must be done before calling ops->remove_interface()



^ permalink raw reply

* [RFC 2/7] mac80211: use common skb queue
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

IBSS, managed and mesh modes all have an
skb queue, and in the future we want to
also use it in other modes, so make them
all use a common skb queue already.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c        |    7 +++----
 net/mac80211/ieee80211_i.h |    7 ++-----
 net/mac80211/iface.c       |   21 +++++++++++----------
 net/mac80211/mesh.c        |   14 ++------------
 net/mac80211/mlme.c        |    5 ++---
 5 files changed, 20 insertions(+), 34 deletions(-)

--- wireless-testing.orig/net/mac80211/ibss.c	2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c	2010-05-28 20:36:59.000000000 +0200
@@ -779,7 +779,7 @@ static void ieee80211_ibss_work(struct w
 		return;
 	ifibss = &sdata->u.ibss;
 
-	while ((skb = skb_dequeue(&ifibss->skb_queue)))
+	while ((skb = skb_dequeue(&sdata->skb_queue)))
 		ieee80211_ibss_rx_queued_mgmt(sdata, skb);
 
 	if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request))
@@ -850,7 +850,6 @@ void ieee80211_ibss_setup_sdata(struct i
 	INIT_WORK(&ifibss->work, ieee80211_ibss_work);
 	setup_timer(&ifibss->timer, ieee80211_ibss_timer,
 		    (unsigned long) sdata);
-	skb_queue_head_init(&ifibss->skb_queue);
 }
 
 /* scan finished notification */
@@ -890,7 +889,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_
 	case IEEE80211_STYPE_BEACON:
 	case IEEE80211_STYPE_PROBE_REQ:
 	case IEEE80211_STYPE_AUTH:
-		skb_queue_tail(&sdata->u.ibss.skb_queue, skb);
+		skb_queue_tail(&sdata->skb_queue, skb);
 		ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
 		return RX_QUEUED;
 	}
@@ -983,7 +982,7 @@ int ieee80211_ibss_leave(struct ieee8021
 	synchronize_rcu();
 	kfree_skb(skb);
 
-	skb_queue_purge(&sdata->u.ibss.skb_queue);
+	skb_queue_purge(&sdata->skb_queue);
 	memset(sdata->u.ibss.bssid, 0, ETH_ALEN);
 	sdata->u.ibss.ssid_len = 0;
 
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-05-28 20:36:59.000000000 +0200
@@ -340,8 +340,6 @@ struct ieee80211_if_managed {
 
 	u16 aid;
 
-	struct sk_buff_head skb_queue;
-
 	unsigned long timers_running; /* used for quiesce/restart */
 	bool powersave; /* powersave requested for this iface */
 	enum ieee80211_smps_mode req_smps, /* requested smps mode */
@@ -388,8 +386,6 @@ struct ieee80211_if_ibss {
 	struct timer_list timer;
 	struct work_struct work;
 
-	struct sk_buff_head skb_queue;
-
 	unsigned long request;
 	unsigned long last_scan_completed;
 
@@ -420,7 +416,6 @@ struct ieee80211_if_mesh {
 	struct timer_list housekeeping_timer;
 	struct timer_list mesh_path_timer;
 	struct timer_list mesh_path_root_timer;
-	struct sk_buff_head skb_queue;
 
 	unsigned long timers_running;
 
@@ -517,6 +512,8 @@ struct ieee80211_sub_if_data {
 
 	u16 sequence_number;
 
+	struct sk_buff_head skb_queue;
+
 	/*
 	 * AP this belongs to: self in AP mode and
 	 * corresponding AP in VLAN mode, NULL for
--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 20:36:01.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 20:36:59.000000000 +0200
@@ -466,21 +466,11 @@ static int ieee80211_stop(struct net_dev
 		cancel_work_sync(&sdata->u.mgd.monitor_work);
 		cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
 
-		/*
-		 * When we get here, the interface is marked down.
-		 * Call synchronize_rcu() to wait for the RX path
-		 * should it be using the interface and enqueuing
-		 * frames at this very time on another CPU.
-		 */
-		synchronize_rcu();
-		skb_queue_purge(&sdata->u.mgd.skb_queue);
 		/* fall through */
 	case NL80211_IFTYPE_ADHOC:
 		if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 			del_timer_sync(&sdata->u.ibss.timer);
 			cancel_work_sync(&sdata->u.ibss.work);
-			synchronize_rcu();
-			skb_queue_purge(&sdata->u.ibss.skb_queue);
 		}
 		/* fall through */
 	case NL80211_IFTYPE_MESH_POINT:
@@ -496,6 +486,15 @@ static int ieee80211_stop(struct net_dev
 		}
 		/* fall through */
 	default:
+		/*
+		 * When we get here, the interface is marked down.
+		 * Call synchronize_rcu() to wait for the RX path
+		 * should it be using the interface and enqueuing
+		 * frames at this very time on another CPU.
+		 */
+		synchronize_rcu();
+		skb_queue_purge(&sdata->skb_queue);
+
 		if (local->scan_sdata == sdata)
 			ieee80211_scan_cancel(local);
 
@@ -722,6 +721,8 @@ static void ieee80211_setup_sdata(struct
 	/* only monitor differs */
 	sdata->dev->type = ARPHRD_ETHER;
 
+	skb_queue_head_init(&sdata->skb_queue);
+
 	switch (type) {
 	case NL80211_IFTYPE_AP:
 		skb_queue_head_init(&sdata->u.ap.ps_bc_buf);
--- wireless-testing.orig/net/mac80211/mesh.c	2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c	2010-05-28 20:36:59.000000000 +0200
@@ -537,15 +537,6 @@ void ieee80211_stop_mesh(struct ieee8021
 	 * it no longer is.
 	 */
 	cancel_work_sync(&sdata->u.mesh.work);
-
-	/*
-	 * When we get here, the interface is marked down.
-	 * Call synchronize_rcu() to wait for the RX path
-	 * should it be using the interface and enqueuing
-	 * frames at this very time on another CPU.
-	 */
-	rcu_barrier(); /* Wait for RX path and call_rcu()'s */
-	skb_queue_purge(&sdata->u.mesh.skb_queue);
 }
 
 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
@@ -650,7 +641,7 @@ static void ieee80211_mesh_work(struct w
 	if (local->scanning)
 		return;
 
-	while ((skb = skb_dequeue(&ifmsh->skb_queue)))
+	while ((skb = skb_dequeue(&sdata->skb_queue)))
 		ieee80211_mesh_rx_queued_mgmt(sdata, skb);
 
 	if (ifmsh->preq_queue_len &&
@@ -690,7 +681,6 @@ void ieee80211_mesh_init_sdata(struct ie
 	setup_timer(&ifmsh->housekeeping_timer,
 		    ieee80211_mesh_housekeeping_timer,
 		    (unsigned long) sdata);
-	skb_queue_head_init(&sdata->u.mesh.skb_queue);
 
 	ifmsh->mshcfg.dot11MeshRetryTimeout = MESH_RET_T;
 	ifmsh->mshcfg.dot11MeshConfirmTimeout = MESH_CONF_T;
@@ -750,7 +740,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_
 	case IEEE80211_STYPE_ACTION:
 	case IEEE80211_STYPE_PROBE_RESP:
 	case IEEE80211_STYPE_BEACON:
-		skb_queue_tail(&ifmsh->skb_queue, skb);
+		skb_queue_tail(&sdata->skb_queue, skb);
 		ieee80211_queue_work(&local->hw, &ifmsh->work);
 		return RX_QUEUED;
 	}
--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 20:36:00.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 20:36:59.000000000 +0200
@@ -1652,7 +1652,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgm
 	case IEEE80211_STYPE_DEAUTH:
 	case IEEE80211_STYPE_DISASSOC:
 	case IEEE80211_STYPE_ACTION:
-		skb_queue_tail(&sdata->u.mgd.skb_queue, skb);
+		skb_queue_tail(&sdata->skb_queue, skb);
 		ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
 		return RX_QUEUED;
 	}
@@ -1810,7 +1810,7 @@ static void ieee80211_sta_work(struct wo
 	ifmgd = &sdata->u.mgd;
 
 	/* first process frames to avoid timing out while a frame is pending */
-	while ((skb = skb_dequeue(&ifmgd->skb_queue)))
+	while ((skb = skb_dequeue(&sdata->skb_queue)))
 		ieee80211_sta_rx_queued_mgmt(sdata, skb);
 
 	/* then process the rest of the work */
@@ -1967,7 +1967,6 @@ void ieee80211_sta_setup_sdata(struct ie
 		    (unsigned long) sdata);
 	setup_timer(&ifmgd->chswitch_timer, ieee80211_chswitch_timer,
 		    (unsigned long) sdata);
-	skb_queue_head_init(&ifmgd->skb_queue);
 
 	ifmgd->flags = 0;
 



^ permalink raw reply

* [RFC 3/7] mac80211: use common work struct
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

IBSS, managed and mesh modes all have their
own work struct, and in the future we want
to also use it in other modes to process
frames from the now common skb queue.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c         |   14 +++++++-------
 net/mac80211/ieee80211_i.h  |    4 +---
 net/mac80211/iface.c        |    4 ++--
 net/mac80211/mesh.c         |   21 ++++++++++-----------
 net/mac80211/mesh_hwmp.c    |    4 ++--
 net/mac80211/mesh_pathtbl.c |    4 ++--
 net/mac80211/mlme.c         |   13 ++++++-------
 7 files changed, 30 insertions(+), 34 deletions(-)

--- wireless-testing.orig/net/mac80211/ibss.c	2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c	2010-05-28 20:37:06.000000000 +0200
@@ -761,7 +761,7 @@ static void ieee80211_ibss_rx_queued_mgm
 static void ieee80211_ibss_work(struct work_struct *work)
 {
 	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, u.ibss.work);
+		container_of(work, struct ieee80211_sub_if_data, work);
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_ibss *ifibss;
 	struct sk_buff *skb;
@@ -804,7 +804,7 @@ static void ieee80211_queue_ibss_work(st
 	struct ieee80211_local *local = sdata->local;
 
 	set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
-	ieee80211_queue_work(&local->hw, &ifibss->work);
+	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
 static void ieee80211_ibss_timer(unsigned long data)
@@ -827,7 +827,7 @@ void ieee80211_ibss_quiesce(struct ieee8
 {
 	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 
-	cancel_work_sync(&ifibss->work);
+	cancel_work_sync(&sdata->work);
 	if (del_timer_sync(&ifibss->timer))
 		ifibss->timer_running = true;
 }
@@ -847,7 +847,7 @@ void ieee80211_ibss_setup_sdata(struct i
 {
 	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 
-	INIT_WORK(&ifibss->work, ieee80211_ibss_work);
+	INIT_WORK(&sdata->work, ieee80211_ibss_work);
 	setup_timer(&ifibss->timer, ieee80211_ibss_timer,
 		    (unsigned long) sdata);
 }
@@ -890,7 +890,7 @@ ieee80211_ibss_rx_mgmt(struct ieee80211_
 	case IEEE80211_STYPE_PROBE_REQ:
 	case IEEE80211_STYPE_AUTH:
 		skb_queue_tail(&sdata->skb_queue, skb);
-		ieee80211_queue_work(&local->hw, &sdata->u.ibss.work);
+		ieee80211_queue_work(&local->hw, &sdata->work);
 		return RX_QUEUED;
 	}
 
@@ -956,7 +956,7 @@ int ieee80211_ibss_join(struct ieee80211
 	ieee80211_recalc_idle(sdata->local);
 
 	set_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
-	ieee80211_queue_work(&sdata->local->hw, &sdata->u.ibss.work);
+	ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 
 	return 0;
 }
@@ -967,7 +967,7 @@ int ieee80211_ibss_leave(struct ieee8021
 
 	del_timer_sync(&sdata->u.ibss.timer);
 	clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
-	cancel_work_sync(&sdata->u.ibss.work);
+	cancel_work_sync(&sdata->work);
 	clear_bit(IEEE80211_IBSS_REQ_RUN, &sdata->u.ibss.request);
 
 	sta_info_flush(sdata->local, sdata);
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-05-28 20:37:06.000000000 +0200
@@ -325,7 +325,6 @@ struct ieee80211_if_managed {
 	struct timer_list conn_mon_timer;
 	struct timer_list bcn_mon_timer;
 	struct timer_list chswitch_timer;
-	struct work_struct work;
 	struct work_struct monitor_work;
 	struct work_struct chswitch_work;
 	struct work_struct beacon_connection_loss_work;
@@ -384,7 +383,6 @@ enum ieee80211_ibss_request {
 
 struct ieee80211_if_ibss {
 	struct timer_list timer;
-	struct work_struct work;
 
 	unsigned long request;
 	unsigned long last_scan_completed;
@@ -412,7 +410,6 @@ struct ieee80211_if_ibss {
 };
 
 struct ieee80211_if_mesh {
-	struct work_struct work;
 	struct timer_list housekeeping_timer;
 	struct timer_list mesh_path_timer;
 	struct timer_list mesh_path_root_timer;
@@ -512,6 +509,7 @@ struct ieee80211_sub_if_data {
 
 	u16 sequence_number;
 
+	struct work_struct work;
 	struct sk_buff_head skb_queue;
 
 	/*
--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 20:37:06.000000000 +0200
@@ -1653,7 +1653,7 @@ ieee80211_rx_result ieee80211_sta_rx_mgm
 	case IEEE80211_STYPE_DISASSOC:
 	case IEEE80211_STYPE_ACTION:
 		skb_queue_tail(&sdata->skb_queue, skb);
-		ieee80211_queue_work(&local->hw, &sdata->u.mgd.work);
+		ieee80211_queue_work(&local->hw, &sdata->work);
 		return RX_QUEUED;
 	}
 
@@ -1779,13 +1779,13 @@ static void ieee80211_sta_timer(unsigned
 		return;
 	}
 
-	ieee80211_queue_work(&local->hw, &ifmgd->work);
+	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
 static void ieee80211_sta_work(struct work_struct *work)
 {
 	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, u.mgd.work);
+		container_of(work, struct ieee80211_sub_if_data, work);
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_managed *ifmgd;
 	struct sk_buff *skb;
@@ -1906,8 +1906,7 @@ static void ieee80211_restart_sta_timer(
 		ieee80211_queue_work(&sdata->local->hw,
 			   &sdata->u.mgd.monitor_work);
 		/* and do all the other regular work too */
-		ieee80211_queue_work(&sdata->local->hw,
-			   &sdata->u.mgd.work);
+		ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 	}
 }
 
@@ -1922,7 +1921,7 @@ void ieee80211_sta_quiesce(struct ieee80
 	 * time -- the code here is properly synchronised.
 	 */
 
-	cancel_work_sync(&ifmgd->work);
+	cancel_work_sync(&sdata->work);
 	cancel_work_sync(&ifmgd->beacon_connection_loss_work);
 	if (del_timer_sync(&ifmgd->timer))
 		set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
@@ -1954,7 +1953,7 @@ void ieee80211_sta_setup_sdata(struct ie
 	struct ieee80211_if_managed *ifmgd;
 
 	ifmgd = &sdata->u.mgd;
-	INIT_WORK(&ifmgd->work, ieee80211_sta_work);
+	INIT_WORK(&sdata->work, ieee80211_sta_work);
 	INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
 	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
 	INIT_WORK(&ifmgd->beacon_connection_loss_work,
--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 20:37:06.000000000 +0200
@@ -461,7 +461,7 @@ static int ieee80211_stop(struct net_dev
 		 * whether the interface is running, which, at this point,
 		 * it no longer is.
 		 */
-		cancel_work_sync(&sdata->u.mgd.work);
+		cancel_work_sync(&sdata->work);
 		cancel_work_sync(&sdata->u.mgd.chswitch_work);
 		cancel_work_sync(&sdata->u.mgd.monitor_work);
 		cancel_work_sync(&sdata->u.mgd.beacon_connection_loss_work);
@@ -470,7 +470,7 @@ static int ieee80211_stop(struct net_dev
 	case NL80211_IFTYPE_ADHOC:
 		if (sdata->vif.type == NL80211_IFTYPE_ADHOC) {
 			del_timer_sync(&sdata->u.ibss.timer);
-			cancel_work_sync(&sdata->u.ibss.work);
+			cancel_work_sync(&sdata->work);
 		}
 		/* fall through */
 	case NL80211_IFTYPE_MESH_POINT:
--- wireless-testing.orig/net/mac80211/mesh.c	2010-05-28 20:36:59.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c	2010-05-28 20:37:06.000000000 +0200
@@ -54,7 +54,7 @@ static void ieee80211_mesh_housekeeping_
 		return;
 	}
 
-	ieee80211_queue_work(&local->hw, &ifmsh->work);
+	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
 /**
@@ -345,7 +345,7 @@ static void ieee80211_mesh_path_timer(un
 		return;
 	}
 
-	ieee80211_queue_work(&local->hw, &ifmsh->work);
+	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
 static void ieee80211_mesh_path_root_timer(unsigned long data)
@@ -362,7 +362,7 @@ static void ieee80211_mesh_path_root_tim
 		return;
 	}
 
-	ieee80211_queue_work(&local->hw, &ifmsh->work);
+	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
 void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh)
@@ -485,7 +485,7 @@ void ieee80211_mesh_quiesce(struct ieee8
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
 	/* might restart the timer but that doesn't matter */
-	cancel_work_sync(&ifmsh->work);
+	cancel_work_sync(&sdata->work);
 
 	/* use atomic bitops in case both timers fire at the same time */
 
@@ -518,7 +518,7 @@ void ieee80211_start_mesh(struct ieee802
 
 	set_bit(MESH_WORK_HOUSEKEEPING, &ifmsh->wrkq_flags);
 	ieee80211_mesh_root_setup(ifmsh);
-	ieee80211_queue_work(&local->hw, &ifmsh->work);
+	ieee80211_queue_work(&local->hw, &sdata->work);
 	sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL;
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON |
 						BSS_CHANGED_BEACON_ENABLED |
@@ -536,7 +536,7 @@ void ieee80211_stop_mesh(struct ieee8021
 	 * whether the interface is running, which, at this point,
 	 * it no longer is.
 	 */
-	cancel_work_sync(&sdata->u.mesh.work);
+	cancel_work_sync(&sdata->work);
 }
 
 static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
@@ -630,7 +630,7 @@ static void ieee80211_mesh_rx_queued_mgm
 static void ieee80211_mesh_work(struct work_struct *work)
 {
 	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, u.mesh.work);
+		container_of(work, struct ieee80211_sub_if_data, work);
 	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct sk_buff *skb;
@@ -669,7 +669,7 @@ void ieee80211_mesh_notify_scan_complete
 	rcu_read_lock();
 	list_for_each_entry_rcu(sdata, &local->interfaces, list)
 		if (ieee80211_vif_is_mesh(&sdata->vif))
-			ieee80211_queue_work(&local->hw, &sdata->u.mesh.work);
+			ieee80211_queue_work(&local->hw, &sdata->work);
 	rcu_read_unlock();
 }
 
@@ -677,7 +677,7 @@ void ieee80211_mesh_init_sdata(struct ie
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
-	INIT_WORK(&ifmsh->work, ieee80211_mesh_work);
+	INIT_WORK(&sdata->work, ieee80211_mesh_work);
 	setup_timer(&ifmsh->housekeeping_timer,
 		    ieee80211_mesh_housekeeping_timer,
 		    (unsigned long) sdata);
@@ -726,7 +726,6 @@ ieee80211_rx_result
 ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
 {
 	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 	struct ieee80211_mgmt *mgmt;
 	u16 fc;
 
@@ -741,7 +740,7 @@ ieee80211_mesh_rx_mgmt(struct ieee80211_
 	case IEEE80211_STYPE_PROBE_RESP:
 	case IEEE80211_STYPE_BEACON:
 		skb_queue_tail(&sdata->skb_queue, skb);
-		ieee80211_queue_work(&local->hw, &ifmsh->work);
+		ieee80211_queue_work(&local->hw, &sdata->work);
 		return RX_QUEUED;
 	}
 
--- wireless-testing.orig/net/mac80211/mesh_hwmp.c	2010-05-28 20:35:59.000000000 +0200
+++ wireless-testing/net/mac80211/mesh_hwmp.c	2010-05-28 20:37:06.000000000 +0200
@@ -805,14 +805,14 @@ static void mesh_queue_preq(struct mesh_
 	spin_unlock(&ifmsh->mesh_preq_queue_lock);
 
 	if (time_after(jiffies, ifmsh->last_preq + min_preq_int_jiff(sdata)))
-		ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
+		ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 
 	else if (time_before(jiffies, ifmsh->last_preq)) {
 		/* avoid long wait if did not send preqs for a long time
 		 * and jiffies wrapped around
 		 */
 		ifmsh->last_preq = jiffies - min_preq_int_jiff(sdata) - 1;
-		ieee80211_queue_work(&sdata->local->hw, &ifmsh->work);
+		ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 	} else
 		mod_timer(&ifmsh->mesh_path_timer, ifmsh->last_preq +
 						min_preq_int_jiff(sdata));
--- wireless-testing.orig/net/mac80211/mesh_pathtbl.c	2010-05-28 20:35:59.000000000 +0200
+++ wireless-testing/net/mac80211/mesh_pathtbl.c	2010-05-28 20:37:06.000000000 +0200
@@ -315,7 +315,7 @@ int mesh_path_add(u8 *dst, struct ieee80
 	read_unlock(&pathtbl_resize_lock);
 	if (grow) {
 		set_bit(MESH_WORK_GROW_MPATH_TABLE,  &ifmsh->wrkq_flags);
-		ieee80211_queue_work(&local->hw, &ifmsh->work);
+		ieee80211_queue_work(&local->hw, &sdata->work);
 	}
 	return 0;
 
@@ -425,7 +425,7 @@ int mpp_path_add(u8 *dst, u8 *mpp, struc
 	read_unlock(&pathtbl_resize_lock);
 	if (grow) {
 		set_bit(MESH_WORK_GROW_MPP_TABLE,  &ifmsh->wrkq_flags);
-		ieee80211_queue_work(&local->hw, &ifmsh->work);
+		ieee80211_queue_work(&local->hw, &sdata->work);
 	}
 	return 0;
 



^ permalink raw reply

* [RFC 4/7] mac80211: use common work function
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Even with the previous patch, IBSS, managed
and mesh modes all attach their own work
function to the shared work struct, which
means some duplicated code. Change that to
only have a frame processing function and a
further work function for each of them and
share some common code.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c        |   29 ++-------------------
 net/mac80211/ieee80211_i.h |   11 +++++++
 net/mac80211/iface.c       |   62 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/mesh.c        |   20 ++------------
 net/mac80211/mlme.c        |   35 ++-----------------------
 5 files changed, 84 insertions(+), 73 deletions(-)

--- wireless-testing.orig/net/mac80211/ibss.c	2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c	2010-05-28 20:37:08.000000000 +0200
@@ -727,8 +727,8 @@ static void ieee80211_rx_mgmt_beacon(str
 	ieee80211_rx_bss_info(sdata, mgmt, len, rx_status, &elems, true);
 }
 
-static void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
-					  struct sk_buff *skb)
+void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+				   struct sk_buff *skb)
 {
 	struct ieee80211_rx_status *rx_status;
 	struct ieee80211_mgmt *mgmt;
@@ -758,29 +758,9 @@ static void ieee80211_ibss_rx_queued_mgm
 	kfree_skb(skb);
 }
 
-static void ieee80211_ibss_work(struct work_struct *work)
+void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
 {
-	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, work);
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_ibss *ifibss;
-	struct sk_buff *skb;
-
-	if (WARN_ON(local->suspended))
-		return;
-
-	if (!ieee80211_sdata_running(sdata))
-		return;
-
-	if (local->scanning)
-		return;
-
-	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_ADHOC))
-		return;
-	ifibss = &sdata->u.ibss;
-
-	while ((skb = skb_dequeue(&sdata->skb_queue)))
-		ieee80211_ibss_rx_queued_mgmt(sdata, skb);
+	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 
 	if (!test_and_clear_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request))
 		return;
@@ -847,7 +827,6 @@ void ieee80211_ibss_setup_sdata(struct i
 {
 	struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
 
-	INIT_WORK(&sdata->work, ieee80211_ibss_work);
 	setup_timer(&ifibss->timer, ieee80211_ibss_timer,
 		    (unsigned long) sdata);
 }
--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-05-28 20:37:08.000000000 +0200
@@ -998,6 +998,9 @@ void ieee80211_sta_process_chanswitch(st
 				      u64 timestamp);
 void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
 void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata);
+void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+				  struct sk_buff *skb);
 
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
@@ -1012,6 +1015,14 @@ int ieee80211_ibss_join(struct ieee80211
 int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
 void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
 void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata);
+void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+				   struct sk_buff *skb);
+
+/* mesh code */
+void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
+void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+				   struct sk_buff *skb);
 
 /* scan/BSS handling */
 void ieee80211_scan_work(struct work_struct *work);
--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 20:37:08.000000000 +0200
@@ -704,6 +704,67 @@ static void ieee80211_if_setup(struct ne
 	dev->destructor = free_netdev;
 }
 
+static void ieee80211_iface_work(struct work_struct *work)
+{
+	struct ieee80211_sub_if_data *sdata =
+		container_of(work, struct ieee80211_sub_if_data, work);
+	struct ieee80211_local *local = sdata->local;
+	struct sk_buff *skb;
+
+	if (!ieee80211_sdata_running(sdata))
+		return;
+
+	if (local->scanning)
+		return;
+
+	/*
+	 * ieee80211_queue_work() should have picked up most cases,
+	 * here we'll pick the the rest.
+	 */
+	if (WARN(local->suspended,
+		 "interface work scheduled while going to suspend\n"))
+		return;
+
+	/* first process frames */
+	while ((skb = skb_dequeue(&sdata->skb_queue))) {
+		switch (sdata->vif.type) {
+		case NL80211_IFTYPE_STATION:
+			ieee80211_sta_rx_queued_mgmt(sdata, skb);
+			break;
+		case NL80211_IFTYPE_ADHOC:
+			ieee80211_ibss_rx_queued_mgmt(sdata, skb);
+			break;
+		case NL80211_IFTYPE_MESH_POINT:
+			if (!ieee80211_vif_is_mesh(&sdata->vif))
+				break;
+			ieee80211_mesh_rx_queued_mgmt(sdata, skb);
+			break;
+		default:
+			WARN(1, "frame for unexpected interface type");
+			kfree_skb(skb);
+			break;
+		}
+	}
+
+	/* then other type-dependent work */
+	switch (sdata->vif.type) {
+	case NL80211_IFTYPE_STATION:
+		ieee80211_sta_work(sdata);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ieee80211_ibss_work(sdata);
+		break;
+	case NL80211_IFTYPE_MESH_POINT:
+		if (!ieee80211_vif_is_mesh(&sdata->vif))
+			break;
+		ieee80211_mesh_work(sdata);
+		break;
+	default:
+		break;
+	}
+}
+
+
 /*
  * Helper function to initialise an interface to a specific type.
  */
@@ -722,6 +783,7 @@ static void ieee80211_setup_sdata(struct
 	sdata->dev->type = ARPHRD_ETHER;
 
 	skb_queue_head_init(&sdata->skb_queue);
+	INIT_WORK(&sdata->work, ieee80211_iface_work);
 
 	switch (type) {
 	case NL80211_IFTYPE_AP:
--- wireless-testing.orig/net/mac80211/mesh.c	2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c	2010-05-28 20:37:08.000000000 +0200
@@ -599,8 +599,8 @@ static void ieee80211_mesh_rx_mgmt_actio
 	}
 }
 
-static void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
-					  struct sk_buff *skb)
+void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+				   struct sk_buff *skb)
 {
 	struct ieee80211_rx_status *rx_status;
 	struct ieee80211_if_mesh *ifmsh;
@@ -627,22 +627,9 @@ static void ieee80211_mesh_rx_queued_mgm
 	kfree_skb(skb);
 }
 
-static void ieee80211_mesh_work(struct work_struct *work)
+void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
 {
-	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, work);
-	struct ieee80211_local *local = sdata->local;
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
-	struct sk_buff *skb;
-
-	if (!ieee80211_sdata_running(sdata))
-		return;
-
-	if (local->scanning)
-		return;
-
-	while ((skb = skb_dequeue(&sdata->skb_queue)))
-		ieee80211_mesh_rx_queued_mgmt(sdata, skb);
 
 	if (ifmsh->preq_queue_len &&
 	    time_after(jiffies,
@@ -677,7 +664,6 @@ void ieee80211_mesh_init_sdata(struct ie
 {
 	struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
 
-	INIT_WORK(&sdata->work, ieee80211_mesh_work);
 	setup_timer(&ifmsh->housekeeping_timer,
 		    ieee80211_mesh_housekeeping_timer,
 		    (unsigned long) sdata);
--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 20:37:06.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 20:37:08.000000000 +0200
@@ -1660,8 +1660,8 @@ ieee80211_rx_result ieee80211_sta_rx_mgm
 	return RX_DROP_MONITOR;
 }
 
-static void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
-					 struct sk_buff *skb)
+void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
+				  struct sk_buff *skb)
 {
 	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 	struct ieee80211_rx_status *rx_status;
@@ -1782,36 +1782,10 @@ static void ieee80211_sta_timer(unsigned
 	ieee80211_queue_work(&local->hw, &sdata->work);
 }
 
-static void ieee80211_sta_work(struct work_struct *work)
+void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
 {
-	struct ieee80211_sub_if_data *sdata =
-		container_of(work, struct ieee80211_sub_if_data, work);
 	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_if_managed *ifmgd;
-	struct sk_buff *skb;
-
-	if (!ieee80211_sdata_running(sdata))
-		return;
-
-	if (local->scanning)
-		return;
-
-	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
-		return;
-
-	/*
-	 * ieee80211_queue_work() should have picked up most cases,
-	 * here we'll pick the the rest.
-	 */
-	if (WARN(local->suspended, "STA MLME work scheduled while "
-		 "going to suspend\n"))
-		return;
-
-	ifmgd = &sdata->u.mgd;
-
-	/* first process frames to avoid timing out while a frame is pending */
-	while ((skb = skb_dequeue(&sdata->skb_queue)))
-		ieee80211_sta_rx_queued_mgmt(sdata, skb);
+	struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
 	/* then process the rest of the work */
 	mutex_lock(&ifmgd->mtx);
@@ -1953,7 +1927,6 @@ void ieee80211_sta_setup_sdata(struct ie
 	struct ieee80211_if_managed *ifmgd;
 
 	ifmgd = &sdata->u.mgd;
-	INIT_WORK(&sdata->work, ieee80211_sta_work);
 	INIT_WORK(&ifmgd->monitor_work, ieee80211_sta_monitor_work);
 	INIT_WORK(&ifmgd->chswitch_work, ieee80211_chswitch_work);
 	INIT_WORK(&ifmgd->beacon_connection_loss_work,



^ permalink raw reply

* [RFC 5/7] mac80211: common work skb freeing
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

All the management processing functions free the
skb after they are done, so this can be done in
the new common code instead.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c  |    2 --
 net/mac80211/iface.c |    3 ++-
 net/mac80211/mesh.c  |    2 --
 net/mac80211/mlme.c  |    5 +----
 4 files changed, 3 insertions(+), 9 deletions(-)

--- wireless-testing.orig/net/mac80211/ibss.c	2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c	2010-05-28 20:37:10.000000000 +0200
@@ -754,8 +754,6 @@ void ieee80211_ibss_rx_queued_mgmt(struc
 		ieee80211_rx_mgmt_auth_ibss(sdata, mgmt, skb->len);
 		break;
 	}
-
-	kfree_skb(skb);
 }
 
 void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
--- wireless-testing.orig/net/mac80211/mesh.c	2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c	2010-05-28 20:37:10.000000000 +0200
@@ -623,8 +623,6 @@ void ieee80211_mesh_rx_queued_mgmt(struc
 		ieee80211_mesh_rx_mgmt_action(sdata, mgmt, skb->len, rx_status);
 		break;
 	}
-
-	kfree_skb(skb);
 }
 
 void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata)
--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 20:37:10.000000000 +0200
@@ -1754,7 +1754,7 @@ void ieee80211_sta_rx_queued_mgmt(struct
 		default:
 			WARN(1, "unexpected: %d", rma);
 		}
-		goto out;
+		return;
 	}
 
 	mutex_unlock(&ifmgd->mtx);
@@ -1762,9 +1762,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
 	if (skb->len >= 24 + 2 /* mgmt + deauth reason */ &&
 	    (fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_DEAUTH)
 		cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
-
- out:
-	kfree_skb(skb);
 }
 
 static void ieee80211_sta_timer(unsigned long data)
--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 20:37:10.000000000 +0200
@@ -741,9 +741,10 @@ static void ieee80211_iface_work(struct
 			break;
 		default:
 			WARN(1, "frame for unexpected interface type");
-			kfree_skb(skb);
 			break;
 		}
+
+		kfree_skb(skb);
 	}
 
 	/* then other type-dependent work */



^ permalink raw reply

* [RFC 6/7] mac80211: pull mgmt frame rx into rx handler
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

Some code is duplicated between ibss, mesh and
managed mode regarding the queueing of management
frames. Since all modes now use a common skb
queue and a common work function, we can pull
the queueing code into the rx handler directly
and remove the duplicated length checks etc.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/ibss.c        |   26 -------------------
 net/mac80211/ieee80211_i.h |    4 --
 net/mac80211/mesh.c        |   25 ------------------
 net/mac80211/mesh.h        |    2 -
 net/mac80211/mlme.c        |   27 -------------------
 net/mac80211/rx.c          |   61 +++++++++++++++++++++++++++++++++++----------
 6 files changed, 48 insertions(+), 97 deletions(-)

--- wireless-testing.orig/net/mac80211/ieee80211_i.h	2010-05-28 20:37:08.000000000 +0200
+++ wireless-testing/net/mac80211/ieee80211_i.h	2010-05-28 20:37:11.000000000 +0200
@@ -985,8 +985,6 @@ int ieee80211_mgd_action(struct ieee8021
 			 enum nl80211_channel_type channel_type,
 			 bool channel_type_valid,
 			 const u8 *buf, size_t len, u64 *cookie);
-ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
-					  struct sk_buff *skb);
 void ieee80211_send_pspoll(struct ieee80211_local *local,
 			   struct ieee80211_sub_if_data *sdata);
 void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency);
@@ -1005,8 +1003,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
 /* IBSS code */
 void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
 void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata);
-ieee80211_rx_result
-ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
 struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
 					u8 *bssid, u8 *addr, u32 supp_rates,
 					gfp_t gfp);
--- wireless-testing.orig/net/mac80211/mesh.h	2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.h	2010-05-28 20:37:11.000000000 +0200
@@ -237,8 +237,6 @@ void ieee80211s_update_metric(struct iee
 		struct sta_info *stainfo, struct sk_buff *skb);
 void ieee80211s_stop(void);
 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata);
-ieee80211_rx_result
-ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb);
 void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata);
 void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata);
 void ieee80211_mesh_root_setup(struct ieee80211_if_mesh *ifmsh);
--- wireless-testing.orig/net/mac80211/ibss.c	2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/ibss.c	2010-05-28 20:37:11.000000000 +0200
@@ -848,32 +848,6 @@ void ieee80211_ibss_notify_scan_complete
 	mutex_unlock(&local->iflist_mtx);
 }
 
-ieee80211_rx_result
-ieee80211_ibss_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_mgmt *mgmt;
-	u16 fc;
-
-	if (skb->len < 24)
-		return RX_DROP_MONITOR;
-
-	mgmt = (struct ieee80211_mgmt *) skb->data;
-	fc = le16_to_cpu(mgmt->frame_control);
-
-	switch (fc & IEEE80211_FCTL_STYPE) {
-	case IEEE80211_STYPE_PROBE_RESP:
-	case IEEE80211_STYPE_BEACON:
-	case IEEE80211_STYPE_PROBE_REQ:
-	case IEEE80211_STYPE_AUTH:
-		skb_queue_tail(&sdata->skb_queue, skb);
-		ieee80211_queue_work(&local->hw, &sdata->work);
-		return RX_QUEUED;
-	}
-
-	return RX_DROP_MONITOR;
-}
-
 int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
 			struct cfg80211_ibss_params *params)
 {
--- wireless-testing.orig/net/mac80211/mesh.c	2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/mesh.c	2010-05-28 20:37:11.000000000 +0200
@@ -705,28 +705,3 @@ void ieee80211_mesh_init_sdata(struct ie
 	INIT_LIST_HEAD(&ifmsh->preq_queue.list);
 	spin_lock_init(&ifmsh->mesh_preq_queue_lock);
 }
-
-ieee80211_rx_result
-ieee80211_mesh_rx_mgmt(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_mgmt *mgmt;
-	u16 fc;
-
-	if (skb->len < 24)
-		return RX_DROP_MONITOR;
-
-	mgmt = (struct ieee80211_mgmt *) skb->data;
-	fc = le16_to_cpu(mgmt->frame_control);
-
-	switch (fc & IEEE80211_FCTL_STYPE) {
-	case IEEE80211_STYPE_ACTION:
-	case IEEE80211_STYPE_PROBE_RESP:
-	case IEEE80211_STYPE_BEACON:
-		skb_queue_tail(&sdata->skb_queue, skb);
-		ieee80211_queue_work(&local->hw, &sdata->work);
-		return RX_QUEUED;
-	}
-
-	return RX_CONTINUE;
-}
--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 20:37:11.000000000 +0200
@@ -1633,33 +1633,6 @@ static void ieee80211_rx_mgmt_beacon(str
 	ieee80211_bss_info_change_notify(sdata, changed);
 }
 
-ieee80211_rx_result ieee80211_sta_rx_mgmt(struct ieee80211_sub_if_data *sdata,
-					  struct sk_buff *skb)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_mgmt *mgmt;
-	u16 fc;
-
-	if (skb->len < 24)
-		return RX_DROP_MONITOR;
-
-	mgmt = (struct ieee80211_mgmt *) skb->data;
-	fc = le16_to_cpu(mgmt->frame_control);
-
-	switch (fc & IEEE80211_FCTL_STYPE) {
-	case IEEE80211_STYPE_PROBE_RESP:
-	case IEEE80211_STYPE_BEACON:
-	case IEEE80211_STYPE_DEAUTH:
-	case IEEE80211_STYPE_DISASSOC:
-	case IEEE80211_STYPE_ACTION:
-		skb_queue_tail(&sdata->skb_queue, skb);
-		ieee80211_queue_work(&local->hw, &sdata->work);
-		return RX_QUEUED;
-	}
-
-	return RX_DROP_MONITOR;
-}
-
 void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
 				  struct sk_buff *skb)
 {
--- wireless-testing.orig/net/mac80211/rx.c	2010-05-28 20:35:58.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c	2010-05-28 20:37:11.000000000 +0200
@@ -1936,8 +1936,11 @@ ieee80211_rx_h_action(struct ieee80211_r
 		if (len < IEEE80211_MIN_ACTION_SIZE + 1)
 			break;
 
-		if (sdata->vif.type == NL80211_IFTYPE_STATION)
-			return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+			skb_queue_tail(&sdata->skb_queue, rx->skb);
+			ieee80211_queue_work(&local->hw, &sdata->work);
+			return RX_QUEUED;
+		}
 
 		switch (mgmt->u.action.u.addba_req.action_code) {
 		case WLAN_ACTION_ADDBA_REQ:
@@ -1989,7 +1992,9 @@ ieee80211_rx_h_action(struct ieee80211_r
 			if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
 				break;
 
-			return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+			skb_queue_tail(&sdata->skb_queue, rx->skb);
+			ieee80211_queue_work(&local->hw, &sdata->work);
+			return RX_QUEUED;
 		}
 		break;
 	case WLAN_CATEGORY_SA_QUERY:
@@ -2007,9 +2012,11 @@ ieee80211_rx_h_action(struct ieee80211_r
 		break;
 	case WLAN_CATEGORY_MESH_PLINK:
 	case WLAN_CATEGORY_MESH_PATH_SEL:
-		if (ieee80211_vif_is_mesh(&sdata->vif))
-			return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
-		break;
+		if (!ieee80211_vif_is_mesh(&sdata->vif))
+			break;
+		skb_queue_tail(&sdata->skb_queue, rx->skb);
+		ieee80211_queue_work(&local->hw, &sdata->work);
+		return RX_QUEUED;
 	}
 
 	/*
@@ -2067,10 +2074,15 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
 {
 	struct ieee80211_sub_if_data *sdata = rx->sdata;
 	ieee80211_rx_result rxs;
+	struct ieee80211_mgmt *mgmt = (void *)rx->skb->data;
+	__le16 stype;
 
 	if (!(rx->flags & IEEE80211_RX_RA_MATCH))
 		return RX_DROP_MONITOR;
 
+	if (rx->skb->len < 24)
+		return RX_DROP_MONITOR;
+
 	if (ieee80211_drop_unencrypted_mgmt(rx))
 		return RX_DROP_UNUSABLE;
 
@@ -2078,16 +2090,39 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_
 	if (rxs != RX_CONTINUE)
 		return rxs;
 
-	if (ieee80211_vif_is_mesh(&sdata->vif))
-		return ieee80211_mesh_rx_mgmt(sdata, rx->skb);
+	stype = mgmt->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
+
+	if (!ieee80211_vif_is_mesh(&sdata->vif) &&
+	    sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+	    sdata->vif.type != NL80211_IFTYPE_STATION)
+		return RX_DROP_MONITOR;
 
-	if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
-		return ieee80211_ibss_rx_mgmt(sdata, rx->skb);
+	switch (stype) {
+	case cpu_to_le16(IEEE80211_STYPE_BEACON):
+	case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+		/* process for all: mesh, mlme, ibss */
+		break;
+	case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+	case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+		/* process only for station */
+		if (sdata->vif.type != NL80211_IFTYPE_STATION)
+			return RX_DROP_MONITOR;
+		break;
+	case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+	case cpu_to_le16(IEEE80211_STYPE_AUTH):
+		/* process only for ibss */
+		if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
+			return RX_DROP_MONITOR;
+		break;
+	default:
+		return RX_DROP_MONITOR;
+	}
 
-	if (sdata->vif.type == NL80211_IFTYPE_STATION)
-		return ieee80211_sta_rx_mgmt(sdata, rx->skb);
+	/* queue up frame and kick off work to process it */
+	skb_queue_tail(&sdata->skb_queue, rx->skb);
+	ieee80211_queue_work(&rx->local->hw, &sdata->work);
 
-	return RX_DROP_MONITOR;
+	return RX_QUEUED;
 }
 
 static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr,



^ permalink raw reply

* [RFC 7/7] mac80211: always process blockack action from workqueue
From: Johannes Berg @ 2010-05-28 18:53 UTC (permalink / raw)
  To: linux-wireless
In-Reply-To: <20100528185302.639535282@sipsolutions.net>

From: Johannes Berg <johannes.berg@intel.com>

To prepare for making the ampdu_action callback
sleep, make mac80211 always process blockack
action frames from the skb queue. This gets rid
of the current special case for managed mode
interfaces as well.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 net/mac80211/iface.c |   35 ++++++++++++++++++++++++++++++++++-
 net/mac80211/mlme.c  |   38 --------------------------------------
 net/mac80211/rx.c    |   29 +++++++++++++----------------
 3 files changed, 47 insertions(+), 55 deletions(-)

--- wireless-testing.orig/net/mac80211/iface.c	2010-05-28 20:37:10.000000000 +0200
+++ wireless-testing/net/mac80211/iface.c	2010-05-28 20:37:13.000000000 +0200
@@ -727,7 +727,40 @@ static void ieee80211_iface_work(struct
 
 	/* first process frames */
 	while ((skb = skb_dequeue(&sdata->skb_queue))) {
-		switch (sdata->vif.type) {
+		struct ieee80211_mgmt *mgmt = (void *)skb->data;
+
+		if (ieee80211_is_action(mgmt->frame_control) &&
+		    mgmt->u.action.category == WLAN_CATEGORY_BACK) {
+			int len = skb->len;
+			struct sta_info *sta;
+
+			rcu_read_lock();
+			sta = sta_info_get(sdata, mgmt->sa);
+			if (sta) {
+				local_bh_disable();
+
+				switch (mgmt->u.action.u.addba_req.action_code) {
+				case WLAN_ACTION_ADDBA_REQ:
+					ieee80211_process_addba_request(
+							local, sta, mgmt, len);
+					break;
+				case WLAN_ACTION_ADDBA_RESP:
+					ieee80211_process_addba_resp(local, sta,
+								     mgmt, len);
+					break;
+				case WLAN_ACTION_DELBA:
+					ieee80211_process_delba(sdata, sta,
+								mgmt, len);
+					break;
+				default:
+					WARN_ON(1);
+					break;
+				}
+
+				local_bh_enable();
+			}
+			rcu_read_unlock();
+		} else switch (sdata->vif.type) {
 		case NL80211_IFTYPE_STATION:
 			ieee80211_sta_rx_queued_mgmt(sdata, skb);
 			break;
--- wireless-testing.orig/net/mac80211/mlme.c	2010-05-28 20:37:11.000000000 +0200
+++ wireless-testing/net/mac80211/mlme.c	2010-05-28 20:37:13.000000000 +0200
@@ -1666,44 +1666,6 @@ void ieee80211_sta_rx_queued_mgmt(struct
 			break;
 		case IEEE80211_STYPE_ACTION:
 			switch (mgmt->u.action.category) {
-			case WLAN_CATEGORY_BACK: {
-				struct ieee80211_local *local = sdata->local;
-				int len = skb->len;
-				struct sta_info *sta;
-
-				rcu_read_lock();
-				sta = sta_info_get(sdata, mgmt->sa);
-				if (!sta) {
-					rcu_read_unlock();
-					break;
-				}
-
-				local_bh_disable();
-
-				switch (mgmt->u.action.u.addba_req.action_code) {
-				case WLAN_ACTION_ADDBA_REQ:
-					if (len < (IEEE80211_MIN_ACTION_SIZE +
-						   sizeof(mgmt->u.action.u.addba_req)))
-						break;
-					ieee80211_process_addba_request(local, sta, mgmt, len);
-					break;
-				case WLAN_ACTION_ADDBA_RESP:
-					if (len < (IEEE80211_MIN_ACTION_SIZE +
-						   sizeof(mgmt->u.action.u.addba_resp)))
-						break;
-					ieee80211_process_addba_resp(local, sta, mgmt, len);
-					break;
-				case WLAN_ACTION_DELBA:
-					if (len < (IEEE80211_MIN_ACTION_SIZE +
-						   sizeof(mgmt->u.action.u.delba)))
-						break;
-					ieee80211_process_delba(sdata, sta, mgmt, len);
-					break;
-				}
-				local_bh_enable();
-				rcu_read_unlock();
-				break;
-				}
 			case WLAN_CATEGORY_SPECTRUM_MGMT:
 				ieee80211_sta_process_chanswitch(sdata,
 						&mgmt->u.action.u.chan_switch.sw_elem,
--- wireless-testing.orig/net/mac80211/rx.c	2010-05-28 20:37:11.000000000 +0200
+++ wireless-testing/net/mac80211/rx.c	2010-05-28 20:37:13.000000000 +0200
@@ -1936,33 +1936,29 @@ ieee80211_rx_h_action(struct ieee80211_r
 		if (len < IEEE80211_MIN_ACTION_SIZE + 1)
 			break;
 
-		if (sdata->vif.type == NL80211_IFTYPE_STATION) {
-			skb_queue_tail(&sdata->skb_queue, rx->skb);
-			ieee80211_queue_work(&local->hw, &sdata->work);
-			return RX_QUEUED;
-		}
-
 		switch (mgmt->u.action.u.addba_req.action_code) {
 		case WLAN_ACTION_ADDBA_REQ:
 			if (len < (IEEE80211_MIN_ACTION_SIZE +
 				   sizeof(mgmt->u.action.u.addba_req)))
-				return RX_DROP_MONITOR;
-			ieee80211_process_addba_request(local, rx->sta, mgmt, len);
-			goto handled;
+				goto invalid;
+			break;
 		case WLAN_ACTION_ADDBA_RESP:
 			if (len < (IEEE80211_MIN_ACTION_SIZE +
 				   sizeof(mgmt->u.action.u.addba_resp)))
-				break;
-			ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
-			goto handled;
+				goto invalid;
+			break;
 		case WLAN_ACTION_DELBA:
 			if (len < (IEEE80211_MIN_ACTION_SIZE +
 				   sizeof(mgmt->u.action.u.delba)))
-				break;
-			ieee80211_process_delba(sdata, rx->sta, mgmt, len);
-			goto handled;
+				goto invalid;
+			break;
+		default:
+			goto invalid;
 		}
-		break;
+
+		skb_queue_tail(&sdata->skb_queue, rx->skb);
+		ieee80211_queue_work(&local->hw, &sdata->work);
+		return RX_QUEUED;
 	case WLAN_CATEGORY_SPECTRUM_MGMT:
 		if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
 			break;
@@ -2019,6 +2015,7 @@ ieee80211_rx_h_action(struct ieee80211_r
 		return RX_QUEUED;
 	}
 
+ invalid:
 	/*
 	 * For AP mode, hostapd is responsible for handling any action
 	 * frames that we didn't handle, including returning unknown



^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox