Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH] mac80211: treat the WME sta flag as a bit
From: Arik Nemtsov @ 2011-09-26  6:36 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg, Arik Nemtsov

Correct flag usage - use it as a bit index instead of a bit value.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
---
 net/wireless/nl80211.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c26a1da..4bb1f48 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2613,7 +2613,7 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 
 	/* parse WME attributes if sta is WME capable */
 	if ((rdev->wiphy.flags & WIPHY_FLAG_AP_UAPSD) &&
-	    (params.sta_flags_set & NL80211_STA_FLAG_WME) &&
+	    (params.sta_flags_set & BIT(NL80211_STA_FLAG_WME)) &&
 	    info->attrs[NL80211_ATTR_STA_WME]) {
 		struct nlattr *tb[NL80211_STA_WME_MAX + 1];
 		struct nlattr *nla;
-- 
1.7.4.1


^ permalink raw reply related

* Re: [PATCH] wl12xx: Add support for HW channel switch
From: Victor Goldenshtein @ 2011-09-26  7:23 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: Levi, Shahar, linux-wireless
In-Reply-To: <1317018322.2171.17.camel@cumari>

On 26/09/2011 09:25, Luciano Coelho wrote:
>>> I checked this a bit further and I don't see the point in sending all
>>> packets here.  In fact, if block_tx is set, we can't even send any more
>>> frames until the switch happens (or fails).  So we should at least check
>>> this here.
>> The block_tx is taken into account in the mac layer.
>
> This is a bit strange, though.  I checked the code and nobody seems to
> be using the block_tx element of ieee80211_channel_switch, so I wonder
> why it's there at all.
>

As far as I know the block_tx is for the DFS channel switch 
implementation, when block_tx=1, the firmware will not start tx on new 
channel.

Victor.

^ permalink raw reply

* Re: Bug in rt2800pci on an RT3090
From: Stanislaw Gruszka @ 2011-09-26  7:55 UTC (permalink / raw)
  To: Bernhard M. Wiedemann
  Cc: Larry Finger, wireless, Ivo van Drn, Gertjan van Wingerde,
	Helmut Schaa, users@rt2x00.serialmonkey.com
In-Reply-To: <4E7E2738.6020208@lsmod.de>

Hello

> the kernel config already has
> CONFIG_LOCKDEP_SUPPORT=y
> Is that what you meant? Does it need any extra to activate?

LOCKDEP_SUPPORT mean that LOCKDEP can be enabled on cpu architecture
for which kernel is build. To enable it you have to use "make menuconfig"
and mark up  "Kernel hacking ---> Lock debugging: prove locking correctness"
After that CONFIG_LOCKDEP=y should show up in .config.

> meanwhile I had a similar bug on rc6 hours after resuming.
>
> This time it had some additional soft lockup messages ontop. see
> http://www.zq1.de/~bernhard/temp/dmesg.bug

Again, lockdep should print more information and allow to debug
this easly.

Stanislaw

^ permalink raw reply

* [patch] wl3501_cs: min_t() cast truncates high bits
From: Dan Carpenter @ 2011-09-26  6:30 UTC (permalink / raw)
  To: Arnaldo Carvalho de Melo
  Cc: John W. Linville, linux-wireless, kernel-janitors

wrqu->encoding.length comes from the network administrator.  It's
size u16.  We want to limit "tocopy" to the smallest value of either
"len_keys", "wrqu->encoding.length" or 100.  But because .length
gets cast from u16 to u8 we might use a random, smaller value than
the was desired.  It's probably not very serious, but we may as well
fix it.

Btw, this is from code auditing and not from testing.  I don't know
if this affects anyone in real life.

Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>

diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
index 6bc7c92..98fbf54 100644
--- a/drivers/net/wireless/wl3501_cs.c
+++ b/drivers/net/wireless/wl3501_cs.c
@@ -1781,7 +1781,7 @@ static int wl3501_get_encode(struct net_device *dev,
 				  keys, len_keys);
 	if (rc)
 		goto out;
-	tocopy = min_t(u8, len_keys, wrqu->encoding.length);
+	tocopy = min_t(u16, len_keys, wrqu->encoding.length);
 	tocopy = min_t(u8, tocopy, 100);
 	wrqu->encoding.length = tocopy;
 	memcpy(extra, keys, tocopy);

^ permalink raw reply related

* Re: Bug in rt2800pci on an RT3090
From: Helmut Schaa @ 2011-09-26  8:20 UTC (permalink / raw)
  To: Larry Finger
  Cc: wireless, Ivo van Drn, Gertjan van Wingerde,
	users@rt2x00.serialmonkey.com, Bernhard M. Wiedemann
In-Reply-To: <4E7CEE67.2070906@lwfinger.net>

On Fri, Sep 23, 2011 at 10:39 PM, Larry Finger
<Larry.Finger@lwfinger.net> wrote:
> A bug was sent to me concerning a scheduling-while-atomic-BUG. This happened
> shortly after KDE suspended an eeepc1015PE netbook during system update over
> WLAN. Suspend&resume normally worked allright. The OP is Berhard Wiedemann
> in the Cc list. Inquiries for more info go to him.
>
> The kernel is 3.1-rc5 from the openSUSE Factory repo on a 32-bit system.
>
> The device is:
>
> 02:00.0 Network controller [0280]: Ralink corp. RT3090 Wireless 802.11n
> 1T/1R PCIe [1814:3090]
>
> The dmesg error dump is
>
> [23281.115155] BUG: scheduling while atomic: kworker/u:22/12821/0x00000101
> [23281.115166] Modules linked in: loop af_packet tun coretemp microcode
> sha256_generic cbc dm_crypt fuse dm_mod arc4 rt2800pci rt2800lib crc_ccitt
> rt2x00pci rt2x00lib mac80211 snd_hda_codec_realtek cfg80211 snd_hda_intel
> snd_hda_codec snd_hwdep snd_pcm uvcvideo videodev snd_timer snd eeepc_wmi
> asus_wmi sparse_keymap pci_hotplug rfkill soundcore eeprom_93cx6
> snd_page_alloc iTCO_wdt sg pcspkr iTCO_vendor_support battery atl1c wmi
> joydev ac autofs4 i915 drm_kms_helper drm i2c_algo_bit button video fan
> thermal processor thermal_sys
> [23281.115299] Modules linked in: loop af_packet tun coretemp microcode
> sha256_generic cbc dm_crypt fuse dm_mod arc4 rt2800pci rt2800lib crc_ccitt
> rt2x00pci rt2x00lib mac80211 snd_hda_codec_realtek cfg80211 snd_hda_intel
> snd_hda_codec snd_hwdep snd_pcm uvcvideo videodev snd_timer snd eeepc_wmi
> asus_wmi sparse_keymap pci_hotplug rfkill soundcore eeprom_93cx6
> snd_page_alloc iTCO_wdt sg pcspkr iTCO_vendor_support battery atl1c wmi
> joydev ac autofs4 i915 drm_kms_helper drm i2c_algo_bit button video fan
> thermal processor thermal_sys
> [23281.115403]
> [23281.115412] Pid: 12821, comm: kworker/u:22 Not tainted
> 3.1.0-rc5-2-desktop #1 ASUSTeK Computer INC. 1015P/1015PE
> [23281.115426] EIP: 0060:[<f7b9c43b>] EFLAGS: 00000282 CPU: 1
> [23281.115440] EIP is at rt2x00pci_regbusy_read+0xb/0xd0 [rt2x00pci]
> [23281.115447] EAX: f2915160 EBX: f2915160 ECX: f7baa2a0 EDX: 00007010
> [23281.115454] ESI: f2915160 EDI: 00007010 EBP: 000000ff ESP: f1db1e2c
> [23281.115461]  DS: 007b ES: 007b FS: 00d8 GS: 0000 SS: 0068
> [23281.115470] Process kworker/u:22 (pid: 12821, ti=f4910000 task=eb86a4b0
> task.ti=f1db0000)
> [23281.115477] Stack:
> [23281.115482]  00000000 f1db1e60 8e97f4be 001e8480 ffffffff eb86a4e4
> f2414f24 eb86a4b0
> [23281.115503]  00000001 f2915160 f29153f0 000000ff f7bce81d 00000018
> ff000000 f1db1e70
> [23281.115521]  013020a0 f1db1e84 f2915160 f2915160 fffffdf4 f2914320
> f7ba8965 000000ff
> [23281.115541] Call Trace:
> [23281.115576]  [<f7bce81d>] rt2800_mcu_request.part.27+0x5d/0xd0
> [rt2800lib]
> [23281.115612]  [<f7ba8965>] rt2800pci_set_state+0x55/0x90 [rt2800pci]
> [23281.115638]  [<f7ba90a5>] rt2800pci_set_device_state+0xd5/0x13b
> [rt2800pci]
> [23281.115670]  [<f7bcdc82>] rt2800_config_ps.isra.19+0x82/0xe0 [rt2800lib]
> [23281.115706]  [<f7bbf5c1>] rt2x00lib_config+0xd1/0x280 [rt2x00lib]
> [23281.115744]  [<f7bbec56>] rt2x00mac_config+0x36/0x80 [rt2x00lib]
> [23281.115789]  [<f8201fb0>] ieee80211_hw_config+0xc0/0x130 [mac80211]
> [23281.115830]  [<f820ca7c>] ieee80211_dynamic_ps_enable_work+0x18c/0x280
> [mac80211]
> [23281.115927]  [<c0262f5e>] process_one_work+0xee/0x400
> [23281.115945]  [<c026356e>] worker_thread+0x11e/0x2c0
> [23281.115960]  [<c0266d19>] kthread+0x69/0x70
> [23281.115976]  [<c070d3e6>] kernel_thread_helper+0x6/0xd
> [23281.115987] Code: 81 fa 00 00 00 01 19 c0 f7 d0 05 d1 00 00 00 eb d4 b8
> f4 ff ff ff eb 8c 90 8d b4 26 00 00 00 00 55 57 89 d7 56 53 89 c3 83 ec 20
> <8b> 8b 38 02 00 00 8b 44 24 38 8b 54 24 34 8b 6c 24 3c 89 44 24
> [23281.116133] Call Trace:
> [23281.116163]  [<f7bce81d>] rt2800_mcu_request.part.27+0x5d/0xd0
> [rt2800lib]
> [23281.116196]  [<f7ba8965>] rt2800pci_set_state+0x55/0x90 [rt2800pci]
> [23281.116220]  [<f7ba90a5>] rt2800pci_set_device_state+0xd5/0x13b
> [rt2800pci]
> [23281.116249]  [<f7bcdc82>] rt2800_config_ps.isra.19+0x82/0xe0 [rt2800lib]
> [23281.116282]  [<f7bbf5c1>] rt2x00lib_config+0xd1/0x280 [rt2x00lib]
> [23281.116318]  [<f7bbec56>] rt2x00mac_config+0x36/0x80 [rt2x00lib]
> [23281.116360]  [<f8201fb0>] ieee80211_hw_config+0xc0/0x130 [mac80211]
> [23281.116397]  [<f820ca7c>] ieee80211_dynamic_ps_enable_work+0x18c/0x280
> [mac80211]
> [23281.116493]  [<c0262f5e>] process_one_work+0xee/0x400
> [23281.116507]  [<c026356e>] worker_thread+0x11e/0x2c0
> [23281.116520]  [<c0266d19>] kthread+0x69/0x70
> [23281.116534]  [<c070d3e6>] kernel_thread_helper+0x6/0xd

This is a bug in the rt2800pci powersave code, the device is woken up in
a tasklet while the MCU request needs to sleep.

A workaround is to disable PS.

Hopefully I can work on a fix soon ...

Helmut

^ permalink raw reply

* Re: [patch] wl3501_cs: min_t() cast truncates high bits
From: Johannes Berg @ 2011-09-26  8:24 UTC (permalink / raw)
  To: Dan Carpenter
  Cc: Arnaldo Carvalho de Melo, John W. Linville, linux-wireless,
	kernel-janitors
In-Reply-To: <20110926063040.GE11832@elgon.mountain>

On Mon, 2011-09-26 at 09:30 +0300, Dan Carpenter wrote:
> wrqu->encoding.length comes from the network administrator.  It's
> size u16.  We want to limit "tocopy" to the smallest value of either
> "len_keys", "wrqu->encoding.length" or 100.  But because .length
> gets cast from u16 to u8 we might use a random, smaller value than
> the was desired.  It's probably not very serious, but we may as well
> fix it.

Nice catch.

> Btw, this is from code auditing and not from testing.  I don't know
> if this affects anyone in real life.

FWIW, it doesn't, the max key length that makes sense is 32 anyway, and
since this is on an output path I doubt the min_t() will ever have done
anything but returned "tocopy" :-)

johannes

> Signed-off-by: Dan Carpenter <dan.carpenter@oracle.com>
> 
> diff --git a/drivers/net/wireless/wl3501_cs.c b/drivers/net/wireless/wl3501_cs.c
> index 6bc7c92..98fbf54 100644
> --- a/drivers/net/wireless/wl3501_cs.c
> +++ b/drivers/net/wireless/wl3501_cs.c
> @@ -1781,7 +1781,7 @@ static int wl3501_get_encode(struct net_device *dev,
>  				  keys, len_keys);
>  	if (rc)
>  		goto out;
> -	tocopy = min_t(u8, len_keys, wrqu->encoding.length);
> +	tocopy = min_t(u16, len_keys, wrqu->encoding.length);
>  	tocopy = min_t(u8, tocopy, 100);
>  	wrqu->encoding.length = tocopy;
>  	memcpy(extra, keys, tocopy);
> --
> 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

* [PATCH] ath6kl: Fix compilation error while compiling w/o debug
From: Rajkumar Manoharan @ 2011-09-26  8:59 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, ath6kl-devel, Rajkumar Manoharan

drivers/net/wireless/ath/ath6kl/htc_hif.o:
In function `ath6kl_debug_fwlog_event':
drivers/net/wireless/ath/ath6kl/debug.h:109:
multiple definition of `ath6kl_debug_fwlog_event'
drivers/net/wireless/ath/ath6kl/debug.o:
drivers/net/wireless/ath/ath6kl/debug.h:109: first defined here
drivers/net/wireless/ath/ath6kl/htc_hif.o:
In function `ath6kl_debug_cleanup':
drivers/net/wireless/ath/ath6kl/debug.h:118:
multiple definition of `ath6kl_debug_cleanup'
drivers/net/wireless/ath/ath6kl/debug.o:
drivers/net/wireless/ath/ath6kl/debug.h:118: first defined here

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/debug.h |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
index f0d6471..89bf8e1 100644
--- a/drivers/net/wireless/ath/ath6kl/debug.h
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -105,7 +105,8 @@ static inline void dump_cred_dist_stats(struct htc_target *target)
 {
 }
 
-void ath6kl_debug_fwlog_event(struct ath6kl *ar, const void *buf, size_t len)
+static inline void ath6kl_debug_fwlog_event(struct ath6kl *ar,
+					    const void *buf, size_t len)
 {
 }
 
@@ -114,7 +115,7 @@ static inline int ath6kl_debug_init(struct ath6kl *ar)
 	return 0;
 }
 
-void ath6kl_debug_cleanup(struct ath6kl *ar)
+static inline void ath6kl_debug_cleanup(struct ath6kl *ar)
 {
 }
 
-- 
1.7.6.4


^ permalink raw reply related

* [PATCH] ath6kl: Remove unnecessary retrieval of first list entry in ath6kl_htc_tx_setup_scat_list()
From: Vasanthakumar Thiagarajan @ 2011-09-26  9:19 UTC (permalink / raw)
  To: kvalo; +Cc: linux-wireless

It is unnecessary to take the first list entry from queue again for
transmission. Sometimes it may look racy when the head of the list
changes between subsequent retrival, but should not happen in
practical.

Reported-by: Jouni Malinen <jouni@qca.qualcomm.com>
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath6kl/htc.c |    1 -
 1 files changed, 0 insertions(+), 1 deletions(-)

diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
index 9aa2e44..feed985 100644
--- a/drivers/net/wireless/ath/ath6kl/htc.c
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -389,7 +389,6 @@ static int ath6kl_htc_tx_setup_scat_list(struct htc_target *target,
 
 		rem_scat -= len;
 		/* now remove it from the queue */
-		packet = list_first_entry(queue, struct htc_packet, list);
 		list_del(&packet->list);
 
 		scat_req->scat_list[i].packet = packet;
-- 
1.7.0.4


^ permalink raw reply related

* Re: ath9k: irq storm after suspend/resume
From: Mohammed Shafi @ 2011-09-26  9:24 UTC (permalink / raw)
  To: Clemens Buchacher; +Cc: linux-wireless, beta992
In-Reply-To: <14be9f3b-4c91-481d-9e52-f3119659fd59@email.android.com>

[-- Attachment #1: Type: text/plain, Size: 489 bytes --]

Hi,
On Thu, Sep 1, 2011 at 11:54 AM, Clemens Buchacher <drizzd@aon.at> wrote:
> Mohammed Shafi <shafi.wireless@gmail.com> wrote:
>>
>>i am bit confused looking at bug comments. please correct me.
>>the bug comments say that disabling/making the Network-Manager to
>>sleep triggers the problem.
> That is correct.

is the issue still seen? any improvement with the attached patch..
will just again take a look at this thread and ath_pci_probe once i
finish my work. thanks!

>



-- 
shafi

[-- Attachment #2: 0001-ath9k-disable-interrupt-before-free_irq.patch --]
[-- Type: text/x-diff, Size: 1271 bytes --]

From 3550cd7a113e17c4e7ced8acbd7f14a3a73586ed Mon Sep 17 00:00:00 2001
From: Mohammed Shafi Shajakhan <mohammed@qca.qualcomm.com>
Date: Sat, 24 Sep 2011 21:07:16 +0530
Subject: [PATCH] ath9k: disable interrupt before free_irq

free_irq claims that for a shared IRQ the caller must ensure that the interrupt is
disabled on the card it drives before calling it. will soon test and
send a proper patch

Signed-off-by: Mohammed Shafi Shajakhan <mohammed@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/pci.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index d67d6ee..35537ca 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -285,11 +285,18 @@ static void ath_pci_remove(struct pci_dev *pdev)
 {
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
 	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
 	void __iomem *mem = sc->mem;
 
 	if (!is_ath9k_unloaded)
 		sc->sc_ah->ah_flags |= AH_UNPLUGGED;
+
+	/* disable interrupts */
+	ah->imask &= ~ATH9K_INT_GLOBAL;
+	ath9k_hw_disable_interrupts(ah);
+
 	ath9k_deinit_device(sc);
+
 	free_irq(sc->irq, sc);
 	ieee80211_free_hw(sc->hw);
 
-- 
1.7.0.4


^ permalink raw reply related

* Re: [PATCH 1/3] cfg80211/mac80211: add netdev param to set_txq_params()
From: Johannes Berg @ 2011-09-26  9:34 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <1316970415-23239-1-git-send-email-eliad@wizery.com>

On Sun, 2011-09-25 at 20:06 +0300, Eliad Peller wrote:

> +++ b/net/wireless/nl80211.c
> @@ -1235,6 +1235,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
>  			goto bad_res;
>  		}
>  
> +		if (!netdev) {
> +			result = -EINVAL;
> +			goto bad_res;
> +		}
> +

I'm a little worried about this change, but I don't think we have a
choice. Technically, it is an API change. I believe that no existing
applications (hostapd is probably the only using this) make use of this
with just the phy (and not the netdev).

johannes


^ permalink raw reply

* Re: [PATCH 3/3] mac80211: pass vif param to conf_tx() callback
From: Johannes Berg @ 2011-09-26  9:36 UTC (permalink / raw)
  To: Eliad Peller; +Cc: linux-wireless
In-Reply-To: <1316970415-23239-3-git-send-email-eliad@wizery.com>

On Sun, 2011-09-25 at 20:06 +0300, Eliad Peller wrote:
> tx params should be configured per interface.
> Add ieee80211_vif param to the conf_tx callback,
> and update all the drivers that use this callback.
> 
> The following spatch was used:
> @rule1@
> struct ieee80211_ops ops;
> identifier conf_tx_op;
> @@
> 	ops.conf_tx = conf_tx_op;
> 
> @rule2@
> identifier rule1.conf_tx_op;
> identifier hw, queue, params;
> @@
> 	conf_tx_op (
> -		struct ieee80211_hw *hw,
> +		struct ieee80211_hw *hw, struct ieee80211_vif *vif,
> 		u16 queue,
> 		const struct ieee80211_tx_queue_params *params) {...}

Nice :-)

Looks good to me. (all 3)

johannes



^ permalink raw reply

* Re: [PATCH 09/20] staging: brcm80211: use endian annotated structures in brcmsmac
From: Johannes Berg @ 2011-09-26  9:37 UTC (permalink / raw)
  To: Arend van Spriel
  Cc: Franky (Zhenhui) Lin, gregkh@suse.de,
	devel@linuxdriverproject.org, linux-wireless@vger.kernel.org
In-Reply-To: <4E7DCE39.1010406@broadcom.com>

On Sat, 2011-09-24 at 14:34 +0200, Arend van Spriel wrote:
> On 09/24/2011 12:38 PM, Johannes Berg wrote:
> > On Fri, 2011-09-23 at 19:08 -0700, Franky Lin wrote:
> >>   struct d11rxhdr {
> >>   	u16 RxFrameSize;
> >>   	u16 PAD;
> >> +	union {
> >> +		struct d11rxhdr_le rxh_le;
> >> +		struct d11rxhdr rxh_cpu;
> >> +	};
> > This seems a little strange. Why would it be both in LE and CPU byte
> > order?
> 
> Indeed. When we receive it from the device it is in LE and we convert it 
> to CPU order for further processing using rxh_cpu.

That seems a confusing and error-prone -- you'll have to remember
whether you're before or after conversion. Would it be possible to have
two versions of the outer structure and change the pointer type at that
point?

johannes


^ permalink raw reply

* [RFC] mac80211: Send nullfunc frames at lower rate
From: Rajkumar Manoharan @ 2011-09-26  9:43 UTC (permalink / raw)
  To: johannes; +Cc: linville, linux-wireless, Rajkumar Manoharan

Recently mac80211 was changed to send nullfunc instead of probe
request for connection monitoring. These nullfunc data frames
are being sent at higer rates and also as aggregated ones. This
could probably delays the nullfunc_ack so the connection is getting
disconnected as max retries reached. In order to improve the
connectivity send the nullfunc at lower rate.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
 net/mac80211/rate.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index f61244c..213e1e9 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -208,7 +208,8 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
 
 	fc = hdr->frame_control;
 
-	return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc);
+	return (info->flags & IEEE80211_TX_CTL_NO_ACK) ||
+		!ieee80211_is_data(fc) || ieee80211_is_nullfunc(fc);
 }
 
 static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
-- 
1.7.6.4


^ permalink raw reply related

* [PATCH] ath9k: optimize tx status update
From: Rajkumar Manoharan @ 2011-09-26  9:42 UTC (permalink / raw)
  To: linville; +Cc: linux-wireless, Rajkumar Manoharan

The recent changes of ath_tx_rc_status makes it to be called
only for the first frame of aggregation or if there is a
single subframe and for all normal frames. And also for all
aggregated frames IEEE80211_TX_STAT_AMPDU will be set. This
patch removes the unnecessary checks and make the ampdu_[ack]_len
to be filled on both aggregation and normal frames.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
 drivers/net/wireless/ath/ath9k/rc.c   |   11 -----------
 drivers/net/wireless/ath/ath9k/xmit.c |    5 ++---
 2 files changed, 2 insertions(+), 14 deletions(-)

diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 4f13018..81c48fb 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1354,20 +1354,9 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
 	if (!priv_sta || !ieee80211_is_data(fc))
 		return;
 
-	/* This packet was aggregated but doesn't carry status info */
-	if ((tx_info->flags & IEEE80211_TX_CTL_AMPDU) &&
-	    !(tx_info->flags & IEEE80211_TX_STAT_AMPDU))
-		return;
-
 	if (tx_info->flags & IEEE80211_TX_STAT_TX_FILTERED)
 		return;
 
-	if (!(tx_info->flags & IEEE80211_TX_STAT_AMPDU)) {
-		tx_info->status.ampdu_ack_len =
-			(tx_info->flags & IEEE80211_TX_STAT_ACK ? 1 : 0);
-		tx_info->status.ampdu_len = 1;
-	}
-
 	if (!(tx_info->flags & IEEE80211_TX_STAT_ACK))
 		tx_status = 1;
 
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index fa3dcfd..f5d4764 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -2043,10 +2043,9 @@ static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
 		tx_info->flags |= IEEE80211_TX_STAT_AMPDU;
 
 		BUG_ON(nbad > nframes);
-
-		tx_info->status.ampdu_len = nframes;
-		tx_info->status.ampdu_ack_len = nframes - nbad;
 	}
+	tx_info->status.ampdu_len = nframes;
+	tx_info->status.ampdu_ack_len = nframes - nbad;
 
 	if ((ts->ts_status & ATH9K_TXERR_FILT) == 0 &&
 	    (tx_info->flags & IEEE80211_TX_CTL_NO_ACK) == 0) {
-- 
1.7.6.4


^ permalink raw reply related

* Re: [PATCH] wl12xx: Add support for HW channel switch
From: Levi, Shahar @ 2011-09-26 10:29 UTC (permalink / raw)
  To: Luciano Coelho; +Cc: linux-wireless
In-Reply-To: <1317018322.2171.17.camel@cumari>

On Mon, Sep 26, 2011 at 9:25 AM, Luciano Coelho <coelho@ti.com> wrote:
> On Sun, 2011-09-25 at 19:08 +0300, Levi, Shahar wrote:
>> On Fri, Sep 23, 2011 at 1:59 PM, Luciano Coelho <coelho@ti.com> wrote:
>> > On Thu, 2011-09-22 at 16:36 +0300, Luciano Coelho wrote:
>> >> On Thu, 2011-09-08 at 13:01 +0300, Shahar Levi wrote:
>> >> > +static void wl12xx_op_channel_switch(struct ieee80211_hw *hw,
>> >> > +                                struct ieee80211_channel_switch *ch_switch)
>> >> > +{
>> >> > +   struct wl1271 *wl = hw->priv;
>> >> > +   int ret;
>> >> > +
>> >> > +   wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch");
>> >> > +
>> >> > +   mutex_lock(&wl->mutex);
>> >> > +
>> >> > +   if (unlikely(wl->state == WL1271_STATE_OFF)) {
>> >> > +           mutex_unlock(&wl->mutex);
>> >> > +           ieee80211_chswitch_done(wl->vif, false);
>> >> > +           return;
>> >> > +   }
>> >> > +
>> >> > +   ret = wl1271_ps_elp_wakeup(wl);
>> >> > +   if (ret < 0)
>> >> > +           goto out;
>> >> > +
>> >> > +   /* send all pending packets */
>> >> > +   wl1271_tx_work_locked(wl);
>> >>
>> >> Is this really needed? Can anyone tell why?
>> I have re- discussed with the FW guys and it seems that when using HW
>> channel switch sending all TX packet isn't needed.
>
> As I suspected. ;)
>
>
>> > I checked this a bit further and I don't see the point in sending all
>> > packets here.  In fact, if block_tx is set, we can't even send any more
>> > frames until the switch happens (or fails).  So we should at least check
>> > this here.
>> The block_tx is taken into account in the mac layer.
>
> This is a bit strange, though.  I checked the code and nobody seems to
> be using the block_tx element of ieee80211_channel_switch, so I wonder
> why it's there at all.
>
> In any case, wouldn't it be a good idea for us to use it and send it to
> the firmware, since our firmware supports it? This way we would also
> block TX packets that are queued in the firmware, wouldn't we?
The FW support blocking TX in case of block_tx. The sepc definition is
to block TX in case of block_tx. Is that peer respectability?

>
>> > I'm leaving this patch out for now until I understand this better.
>> Do you prefer me to set v2 without that line or you could fix that in
>> the apply stage?
>
> No need to send v2.  It seems that Victor will need this change for
> something else he's working on, so I guess he can take it over once it
> is needed.  I don't want to include this unless we have a good reason to
> do it.
There is a good reason to include this:
a) It solve STA calibration issue in the FW in case of SW channel
switch (Rx issues)
b) This is FW support for channel switch with one command instead of
using several commands: rate_policies, roc \ join...

Our latest version pass full test cycle with that fix that solve CS issues.
> --
> Cheers,
> Luca.
All the best,
Shahar

^ permalink raw reply

* [PATCH 0/5] TDLS support for nl80211/mac80211 drivers
From: Arik Nemtsov @ 2011-09-26 10:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalyan C Gaddam, Arik Nemtsov

This series adds basic kernel-mode TDLS support for nl80211 based drivers.
It is based in part on patches by Kalyan C. Gaddam, cc-ed here.

Support is added for peer discovery and data path setup/teardown.
Currently not implemented: QoS/HT, peer PSM, peer U-APSD and channel
switching.

The main change from the RFC series is the addition of a Tx block
during link setup. In the new scheme of things, a STA entry is added
just before setting up a link. This allows us to throw out frames
sent to a peer while the link is being set up. This is required by
the specification, to avoid reordering of MSDUs.

User-mode support is added in a companion series.

Tested with wl12xx hardware, with a nl80211/mac80211 based driver.

Arik

Cc: Kalyan C Gaddam <chakkal@iit.edu>

Arik Nemtsov (5):
  nl80211: support sending TDLS commands/frames
  mac80211: standardize adding supported rates IEs
  mac80211: handle TDLS high-level commands and frames
  nl80211/mac80211: allow adding TDLS peers as stations
  mac80211: data path modification for TDLS peers

 include/linux/ieee80211.h |   85 ++++++++++++
 include/linux/if_ether.h  |    1 +
 include/linux/nl80211.h   |   48 +++++++
 include/net/cfg80211.h    |   17 +++
 include/net/mac80211.h    |    5 +
 net/mac80211/Kconfig      |   12 ++
 net/mac80211/cfg.c        |  335 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/main.c       |    4 +
 net/mac80211/mesh.c       |   58 --------
 net/mac80211/mesh.h       |    4 -
 net/mac80211/mesh_plink.c |    4 +-
 net/mac80211/mlme.c       |    7 +-
 net/mac80211/sta_info.h   |    5 +
 net/mac80211/tx.c         |   46 ++++++-
 net/mac80211/util.c       |   59 ++++++++
 net/wireless/nl80211.c    |   97 ++++++++++++-
 net/wireless/util.c       |    5 +-
 17 files changed, 711 insertions(+), 81 deletions(-)

-- 
1.7.4.1


^ permalink raw reply

* [PATCH 1/5] nl80211: support sending TDLS commands/frames
From: Arik Nemtsov @ 2011-09-26 10:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalyan C Gaddam, Arik Nemtsov
In-Reply-To: <1317034493-5300-1-git-send-email-arik@wizery.com>

Add support for sending high-level TDLS commands and TDLS frames via
NL80211_CMD_TDLS_OPER and NL80211_CMD_TDLS_MGMT, respectively. Add
appropriate cfg80211 callbacks for lower level drivers.

Add wiphy capability flags for TDLS support and advertise them via
nl80211.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
---
 include/linux/nl80211.h |   46 ++++++++++++++++++++++++++++
 include/net/cfg80211.h  |   17 ++++++++++
 net/wireless/nl80211.c  |   77 ++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 139 insertions(+), 1 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 460b12a..1582916 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -502,6 +502,9 @@
  * @NL80211_CMD_PMKSA_CANDIDATE: This is used as an event to inform userspace
  *	of PMKSA caching dandidates.
  *
+ * @NL80211_CMD_TDLS_OPER: Perform a high-level TDLS command (e.g. link setup).
+ * @NL80211_CMD_TDLS_MGMT: Send a TDLS management frame.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -628,6 +631,9 @@ enum nl80211_commands {
 
 	NL80211_CMD_PMKSA_CANDIDATE,
 
+	NL80211_CMD_TDLS_OPER,
+	NL80211_CMD_TDLS_MGMT,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1078,6 +1084,20 @@ enum nl80211_commands {
  * @NL80211_ATTR_PMKSA_CANDIDATE: Nested attribute containing the PMKSA caching
  *	candidate information, see &enum nl80211_pmksa_candidate_attr.
  *
+ * @NL80211_ATTR_TDLS_ACTION: Low level TDLS action code (e.g. link setup
+ *	request, link setup confirm, link teardown, etc.). Values are
+ *	described in the TDLS (802.11z) specification.
+ * @NL80211_ATTR_TDLS_DIALOG_TOKEN: Non-zero token for uniquely identifying a
+ *	TDLS conversation between two devices.
+ * @NL80211_ATTR_TDLS_OPERATION: High level TDLS operation; see
+ *	&enum nl80211_tdls_operation, represented as a u8.
+ * @NL80211_ATTR_TDLS_SUPPORT: A flag indicating the device can operate
+ *	as a TDLS peer sta.
+ * @NL80211_ATTR_TDLS_EXTERNAL_SETUP: The TDLS discovery/setup and teardown
+ *	procedures should be performed by sending TDLS packets via
+ *	%NL80211_CMD_TDLS_MGMT. Otherwise %NL80211_CMD_TDLS_OPER should be
+ *	used for asking the driver to perform a TDLS operation.
+ *
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
  */
@@ -1298,6 +1318,12 @@ enum nl80211_attrs {
 
 	NL80211_ATTR_PMKSA_CANDIDATE,
 
+	NL80211_ATTR_TDLS_ACTION,
+	NL80211_ATTR_TDLS_DIALOG_TOKEN,
+	NL80211_ATTR_TDLS_OPERATION,
+	NL80211_ATTR_TDLS_SUPPORT,
+	NL80211_ATTR_TDLS_EXTERNAL_SETUP,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -2591,4 +2617,24 @@ enum nl80211_pmksa_candidate_attr {
 	MAX_NL80211_PMKSA_CANDIDATE = NUM_NL80211_PMKSA_CANDIDATE - 1
 };
 
+/**
+ * enum nl80211_tdls_operation - values for %NL80211_ATTR_TDLS_OPERATION
+ * @NL80211_TDLS_DISCOVERY_REQ: Send a TDLS discovery request
+ * @NL80211_TDLS_SETUP: Setup TDLS link
+ * @NL80211_TDLS_TEARDOWN: Teardown a TDLS link which is already established
+ * @NL80211_TDLS_ENABLE_LINK: Enable TDLS link
+ * @NL80211_TDLS_DISABLE_LINK: Disable TDLS link
+ * @NL80211_TDLS_ENABLE: (Re-)Enable TDLS operation
+ * @NL80211_TDLS_DISABLE: Disable TDLS operation
+ */
+enum nl80211_tdls_operation {
+	NL80211_TDLS_DISCOVERY_REQ,
+	NL80211_TDLS_SETUP,
+	NL80211_TDLS_TEARDOWN,
+	NL80211_TDLS_ENABLE_LINK,
+	NL80211_TDLS_DISABLE_LINK,
+	NL80211_TDLS_ENABLE,
+	NL80211_TDLS_DISABLE
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index ccfdf3f..63a2e31 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1408,6 +1408,9 @@ struct cfg80211_gtk_rekey_data {
  * @set_ringparam: Set tx and rx ring sizes.
  *
  * @get_ringparam: Get tx and rx ring current and maximum sizes.
+ *
+ * @tdls_mgmt: Transmit a TDLS management frame.
+ * @tdls_oper: Perform a high-level TDLS operation (e.g. TDLS link setup).
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -1590,6 +1593,12 @@ struct cfg80211_ops {
 
 	int	(*set_rekey_data)(struct wiphy *wiphy, struct net_device *dev,
 				  struct cfg80211_gtk_rekey_data *data);
+
+	int	(*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
+			     u8 *peer, u8 action_code,  u8 dialog_token,
+			     u16 status_code, const u8 *buf, size_t len);
+	int	(*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
+			     u8 *peer, enum nl80211_tdls_operation oper);
 };
 
 /*
@@ -1642,6 +1651,12 @@ struct cfg80211_ops {
  * @WIPHY_FLAG_SUPPORTS_FW_ROAM: The device supports roaming feature in the
  *	firmware.
  * @WIPHY_FLAG_AP_UAPSD: The device supports uapsd on AP.
+ * @WIPHY_FLAG_SUPPORTS_TDLS: The device supports TDLS (802.11z) operation.
+ * @WIPHY_FLAG_TDLS_EXTERNAL_SETUP: The device does not handle TDLS (802.11z)
+ *	link setup/discovery operations internally. Setup, discovery and
+ *	teardown packets should be sent through the @NL80211_CMD_TDLS_MGMT
+ *	command. When this flag is not set, @NL80211_CMD_TDLS_OPER should be
+ *	used for asking the driver/firmware to perform a TDLS operation.
  */
 enum wiphy_flags {
 	WIPHY_FLAG_CUSTOM_REGULATORY		= BIT(0),
@@ -1658,6 +1673,8 @@ enum wiphy_flags {
 	WIPHY_FLAG_ENFORCE_COMBINATIONS		= BIT(12),
 	WIPHY_FLAG_SUPPORTS_FW_ROAM		= BIT(13),
 	WIPHY_FLAG_AP_UAPSD			= BIT(14),
+	WIPHY_FLAG_SUPPORTS_TDLS		= BIT(15),
+	WIPHY_FLAG_TDLS_EXTERNAL_SETUP		= BIT(16),
 };
 
 /**
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c26a1da..ed9e6d8 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -191,6 +191,11 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = {
 					 .len = IEEE80211_MAX_DATA_LEN },
 	[NL80211_ATTR_ROAM_SUPPORT] = { .type = NLA_FLAG },
 	[NL80211_ATTR_SCHED_SCAN_MATCH] = { .type = NLA_NESTED },
+	[NL80211_ATTR_TDLS_ACTION] = { .type = NLA_U8 },
+	[NL80211_ATTR_TDLS_DIALOG_TOKEN] = { .type = NLA_U8 },
+	[NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 },
+	[NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG },
+	[NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -731,9 +736,12 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 		NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_MESH_AUTH);
 	if (dev->wiphy.flags & WIPHY_FLAG_AP_UAPSD)
 		NLA_PUT_FLAG(msg, NL80211_ATTR_SUPPORT_AP_UAPSD);
-
 	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_FW_ROAM)
 		NLA_PUT_FLAG(msg, NL80211_ATTR_ROAM_SUPPORT);
+	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_SUPPORT);
+	if (dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)
+		NLA_PUT_FLAG(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP);
 
 	NLA_PUT(msg, NL80211_ATTR_CIPHER_SUITES,
 		sizeof(u32) * dev->wiphy.n_cipher_suites,
@@ -876,6 +884,8 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
 	}
 	CMD(set_channel, SET_CHANNEL);
 	CMD(set_wds_peer, SET_WDS_PEER);
+	CMD(tdls_mgmt, TDLS_MGMT);
+	CMD(tdls_oper, TDLS_OPER);
 	if (dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN)
 		CMD(sched_scan_start, START_SCHED_SCAN);
 
@@ -4972,6 +4982,55 @@ static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
 	return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
 }
 
+static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	u8 action_code, dialog_token;
+	u16 status_code;
+	u8 *peer;
+
+	if (!rdev->ops->tdls_mgmt)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_TDLS_ACTION] ||
+	    !info->attrs[NL80211_ATTR_STATUS_CODE] ||
+	    !info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN] ||
+	    !info->attrs[NL80211_ATTR_IE] ||
+	    !info->attrs[NL80211_ATTR_MAC])
+		return -EINVAL;
+
+	peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
+	action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]);
+	status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
+	dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]);
+
+	return rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code,
+				    dialog_token, status_code,
+				    nla_data(info->attrs[NL80211_ATTR_IE]),
+				    nla_len(info->attrs[NL80211_ATTR_IE]));
+}
+
+static int nl80211_tdls_oper(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	enum nl80211_tdls_operation operation;
+	u8 *peer;
+
+	if (!rdev->ops->tdls_oper)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_TDLS_OPERATION] ||
+	    !info->attrs[NL80211_ATTR_MAC])
+		return -EINVAL;
+
+	operation = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_OPERATION]);
+	peer = nla_data(info->attrs[NL80211_ATTR_MAC]);
+
+	return rdev->ops->tdls_oper(&rdev->wiphy, dev, peer, operation);
+}
+
 static int nl80211_remain_on_channel(struct sk_buff *skb,
 				     struct genl_info *info)
 {
@@ -6284,6 +6343,22 @@ static struct genl_ops nl80211_ops[] = {
 		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_TDLS_MGMT,
+		.doit = nl80211_tdls_mgmt,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
+	{
+		.cmd = NL80211_CMD_TDLS_OPER,
+		.doit = nl80211_tdls_oper,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 static struct genl_multicast_group nl80211_mlme_mcgrp = {
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 2/5] mac80211: standardize adding supported rates IEs
From: Arik Nemtsov @ 2011-09-26 10:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalyan C Gaddam, Arik Nemtsov
In-Reply-To: <1317034493-5300-1-git-send-email-arik@wizery.com>

Relocate the mesh implementation of adding the (extended) supported
rates IE to util.c, anticipating its use by other parts of mac80211.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
---
 include/net/mac80211.h    |    5 ++++
 net/mac80211/mesh.c       |   58 --------------------------------------------
 net/mac80211/mesh.h       |    4 ---
 net/mac80211/mesh_plink.c |    4 +-
 net/mac80211/tx.c         |    4 +-
 net/mac80211/util.c       |   59 +++++++++++++++++++++++++++++++++++++++++++++
 6 files changed, 68 insertions(+), 66 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index c0f63fd..4dfead6 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -3439,4 +3439,9 @@ void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
 				   int rssi_max_thold);
 
 void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif);
+
+int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb);
+
+int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif,
+				struct sk_buff *skb);
 #endif /* MAC80211_H */
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index a4225ae..a7078fd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -320,64 +320,6 @@ mesh_add_rsn_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
 	return 0;
 }
 
-int
-mesh_add_srates_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_supported_band *sband;
-	int rate;
-	u8 i, rates, *pos;
-
-	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-	rates = sband->n_bitrates;
-	if (rates > 8)
-		rates = 8;
-
-	if (skb_tailroom(skb) < rates + 2)
-		return -ENOMEM;
-
-	pos = skb_put(skb, rates + 2);
-	*pos++ = WLAN_EID_SUPP_RATES;
-	*pos++ = rates;
-	for (i = 0; i < rates; i++) {
-		rate = sband->bitrates[i].bitrate;
-		*pos++ = (u8) (rate / 5);
-	}
-
-	return 0;
-}
-
-int
-mesh_add_ext_srates_ie(struct sk_buff *skb,
-		       struct ieee80211_sub_if_data *sdata)
-{
-	struct ieee80211_local *local = sdata->local;
-	struct ieee80211_supported_band *sband;
-	int rate;
-	u8 i, exrates, *pos;
-
-	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-	exrates = sband->n_bitrates;
-	if (exrates > 8)
-		exrates -= 8;
-	else
-		exrates = 0;
-
-	if (skb_tailroom(skb) < exrates + 2)
-		return -ENOMEM;
-
-	if (exrates) {
-		pos = skb_put(skb, exrates + 2);
-		*pos++ = WLAN_EID_EXT_SUPP_RATES;
-		*pos++ = exrates;
-		for (i = 8; i < sband->n_bitrates; i++) {
-			rate = sband->bitrates[i].bitrate;
-			*pos++ = (u8) (rate / 5);
-		}
-	}
-	return 0;
-}
-
 int mesh_add_ds_params_ie(struct sk_buff *skb,
 			  struct ieee80211_sub_if_data *sdata)
 {
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 7118e8e..8c00e2d 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -210,10 +210,6 @@ int mesh_add_rsn_ie(struct sk_buff *skb,
 		    struct ieee80211_sub_if_data *sdata);
 int mesh_add_vendor_ies(struct sk_buff *skb,
 			struct ieee80211_sub_if_data *sdata);
-int mesh_add_srates_ie(struct sk_buff *skb,
-		       struct ieee80211_sub_if_data *sdata);
-int mesh_add_ext_srates_ie(struct sk_buff *skb,
-			   struct ieee80211_sub_if_data *sdata);
 int mesh_add_ds_params_ie(struct sk_buff *skb,
 			  struct ieee80211_sub_if_data *sdata);
 void mesh_rmc_free(struct ieee80211_sub_if_data *sdata);
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 1213a23..9cc5029 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -185,8 +185,8 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata,
 			pos = skb_put(skb, 2);
 			memcpy(pos + 2, &plid, 2);
 		}
-		if (mesh_add_srates_ie(skb, sdata) ||
-		    mesh_add_ext_srates_ie(skb, sdata) ||
+		if (ieee80211_add_srates_ie(&sdata->vif, skb) ||
+		    ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
 		    mesh_add_rsn_ie(skb, sdata) ||
 		    mesh_add_meshid_ie(skb, sdata) ||
 		    mesh_add_meshconf_ie(skb, sdata))
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 7cd6c28..542272a 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2307,9 +2307,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
 		*pos++ = WLAN_EID_SSID;
 		*pos++ = 0x0;
 
-		if (mesh_add_srates_ie(skb, sdata) ||
+		if (ieee80211_add_srates_ie(&sdata->vif, skb) ||
 		    mesh_add_ds_params_ie(skb, sdata) ||
-		    mesh_add_ext_srates_ie(skb, sdata) ||
+		    ieee80211_add_ext_srates_ie(&sdata->vif, skb) ||
 		    mesh_add_rsn_ie(skb, sdata) ||
 		    mesh_add_meshid_ie(skb, sdata) ||
 		    mesh_add_meshconf_ie(skb, sdata) ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4b1466d..6926c99 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1353,3 +1353,62 @@ void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
 	_ieee80211_enable_rssi_reports(sdata, 0, 0);
 }
 EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
+
+int ieee80211_add_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_supported_band *sband;
+	int rate;
+	u8 i, rates, *pos;
+
+	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+	rates = sband->n_bitrates;
+	if (rates > 8)
+		rates = 8;
+
+	if (skb_tailroom(skb) < rates + 2)
+		return -ENOMEM;
+
+	pos = skb_put(skb, rates + 2);
+	*pos++ = WLAN_EID_SUPP_RATES;
+	*pos++ = rates;
+	for (i = 0; i < rates; i++) {
+		rate = sband->bitrates[i].bitrate;
+		*pos++ = (u8) (rate / 5);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_add_srates_ie);
+
+int ieee80211_add_ext_srates_ie(struct ieee80211_vif *vif, struct sk_buff *skb)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_supported_band *sband;
+	int rate;
+	u8 i, exrates, *pos;
+
+	sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
+	exrates = sband->n_bitrates;
+	if (exrates > 8)
+		exrates -= 8;
+	else
+		exrates = 0;
+
+	if (skb_tailroom(skb) < exrates + 2)
+		return -ENOMEM;
+
+	if (exrates) {
+		pos = skb_put(skb, exrates + 2);
+		*pos++ = WLAN_EID_EXT_SUPP_RATES;
+		*pos++ = exrates;
+		for (i = 8; i < sband->n_bitrates; i++) {
+			rate = sband->bitrates[i].bitrate;
+			*pos++ = (u8) (rate / 5);
+		}
+	}
+	return 0;
+}
+EXPORT_SYMBOL(ieee80211_add_ext_srates_ie);
\ No newline at end of file
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 3/5] mac80211: handle TDLS high-level commands and frames
From: Arik Nemtsov @ 2011-09-26 10:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalyan C Gaddam, Arik Nemtsov
In-Reply-To: <1317034493-5300-1-git-send-email-arik@wizery.com>

Register and implement the TDLS cfg80211 callback functions.

Internally prepare and send TDLS management frames. We incorporate
local STA capabilities and supported rates with extra IEs given by
usermode. The resulting packet is either encapsulated in a data frame,
or assembled as an action frame. It is transmitted either directly or
through the AP, as mandated by the TDLS specification.

Declare support for the TDLS external setup wiphy capability. This
tells usermode to handle link setup and discovery on its own, and use the
kernel driver for sending TDLS mgmt packets.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
---
 include/linux/ieee80211.h |   85 ++++++++++++
 include/linux/if_ether.h  |    1 +
 net/mac80211/Kconfig      |   12 ++
 net/mac80211/cfg.c        |  314 +++++++++++++++++++++++++++++++++++++++++++++
 net/mac80211/main.c       |    4 +
 5 files changed, 416 insertions(+), 0 deletions(-)

diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index b5e0a5c..f5c8ced 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -759,6 +759,12 @@ struct ieee80211_mgmt {
 					u8 action;
 					u8 smps_control;
 				} __attribute__ ((packed)) ht_smps;
+				struct {
+					u8 action_code;
+					u8 dialog_token;
+					__le16 capability;
+					u8 variable[0];
+				} __packed tdls_discover_resp;
 			} u;
 		} __attribute__ ((packed)) action;
 	} u;
@@ -805,6 +811,52 @@ struct ieee80211_pspoll {
 	u8 ta[6];
 } __attribute__ ((packed));
 
+/* TDLS */
+
+/* Link-id information element */
+struct ieee80211_tdls_lnkie {
+	u8 ie_type; /* Link Identifier IE */
+	u8 ie_len;
+	u8 bssid[6];
+	u8 init_sta[6];
+	u8 resp_sta[6];
+} __packed;
+
+struct ieee80211_tdls_data {
+	u8 da[6];
+	u8 sa[6];
+	__be16 ether_type;
+	u8 payload_type;
+	u8 category;
+	u8 action_code;
+	union {
+		struct {
+			u8 dialog_token;
+			__le16 capability;
+			u8 variable[0];
+		} __packed setup_req;
+		struct {
+			__le16 status_code;
+			u8 dialog_token;
+			__le16 capability;
+			u8 variable[0];
+		} __packed setup_resp;
+		struct {
+			__le16 status_code;
+			u8 dialog_token;
+			u8 variable[0];
+		} __packed setup_cfm;
+		struct {
+			__le16 reason_code;
+			u8 variable[0];
+		} __packed teardown;
+		struct {
+			u8 dialog_token;
+			u8 variable[0];
+		} __packed discover_req;
+	} u;
+} __packed;
+
 /**
  * struct ieee80211_bar - HT Block Ack Request
  *
@@ -1196,6 +1248,8 @@ enum ieee80211_eid {
 	WLAN_EID_TS_DELAY = 43,
 	WLAN_EID_TCLAS_PROCESSING = 44,
 	WLAN_EID_QOS_CAPA = 46,
+	/* 802.11z */
+	WLAN_EID_LINK_ID = 101,
 	/* 802.11s */
 	WLAN_EID_MESH_CONFIG = 113,
 	WLAN_EID_MESH_ID = 114,
@@ -1279,6 +1333,7 @@ enum ieee80211_category {
 	WLAN_CATEGORY_HT = 7,
 	WLAN_CATEGORY_SA_QUERY = 8,
 	WLAN_CATEGORY_PROTECTED_DUAL_OF_ACTION = 9,
+	WLAN_CATEGORY_TDLS = 12,
 	WLAN_CATEGORY_MESH_ACTION = 13,
 	WLAN_CATEGORY_MULTIHOP_ACTION = 14,
 	WLAN_CATEGORY_SELF_PROTECTED = 15,
@@ -1342,6 +1397,36 @@ enum ieee80211_key_len {
 	WLAN_KEY_LEN_AES_CMAC = 16,
 };
 
+/* Public action codes */
+enum ieee80211_pub_actioncode {
+	WLAN_PUB_ACTION_TDLS_DISCOVER_RES = 14,
+};
+
+/* TDLS action codes */
+enum ieee80211_tdls_actioncode {
+	WLAN_TDLS_SETUP_REQUEST = 0,
+	WLAN_TDLS_SETUP_RESPONSE = 1,
+	WLAN_TDLS_SETUP_CONFIRM = 2,
+	WLAN_TDLS_TEARDOWN = 3,
+	WLAN_TDLS_PEER_TRAFFIC_INDICATION = 4,
+	WLAN_TDLS_CHANNEL_SWITCH_REQUEST = 5,
+	WLAN_TDLS_CHANNEL_SWITCH_RESPONSE = 6,
+	WLAN_TDLS_PEER_PSM_REQUEST = 7,
+	WLAN_TDLS_PEER_PSM_RESPONSE = 8,
+	WLAN_TDLS_PEER_TRAFFIC_RESPONSE = 9,
+	WLAN_TDLS_DISCOVERY_REQUEST = 10,
+};
+
+/*
+ * TDLS capabililites to be enabled in the 5th byte of the
+ * @WLAN_EID_EXT_CAPABILITY information element
+ */
+#define WLAN_EXT_CAPA_TDLS_ENABLED	BIT(5)
+#define WLAN_EXT_CAPA_TDLS_PROHIBITED	BIT(6)
+
+/* TDLS specific payload type in the LLC/SNAP header */
+#define WLAN_TDLS_SNAP_RFTYPE	0x2
+
 /**
  * enum - mesh path selection protocol identifier
  *
diff --git a/include/linux/if_ether.h b/include/linux/if_ether.h
index a3d99ff..49c38fc 100644
--- a/include/linux/if_ether.h
+++ b/include/linux/if_ether.h
@@ -83,6 +83,7 @@
 #define ETH_P_8021AH	0x88E7          /* 802.1ah Backbone Service Tag */
 #define ETH_P_1588	0x88F7		/* IEEE 1588 Timesync */
 #define ETH_P_FCOE	0x8906		/* Fibre Channel over Ethernet  */
+#define ETH_P_TDLS	0x890D          /* TDLS */
 #define ETH_P_FIP	0x8914		/* FCoE Initialization Protocol */
 #define ETH_P_QINQ1	0x9100		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
 #define ETH_P_QINQ2	0x9200		/* deprecated QinQ VLAN [ NOT AN OFFICIALLY REGISTERED ID ] */
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index d1886b5..7d3b438 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -225,6 +225,18 @@ config MAC80211_VERBOSE_MHWMP_DEBUG
 
 	  Do not select this option.
 
+config MAC80211_VERBOSE_TDLS_DEBUG
+	bool "Verbose TDLS debugging"
+	depends on MAC80211_DEBUG_MENU
+	---help---
+	  Selecting this option causes mac80211 to print out very
+	  verbose TDLS selection debugging messages (when mac80211
+	  is a TDLS STA).
+	  It should not be selected on production systems as those
+	  messages are remotely triggerable.
+
+	  Do not select this option.
+
 config MAC80211_DEBUG_COUNTERS
 	bool "Extra statistics for TX/RX debugging"
 	depends on MAC80211_DEBUG_MENU
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b57ddf9..1adf823 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <net/net_namespace.h>
 #include <linux/rcupdate.h>
+#include <linux/if_ether.h>
 #include <net/cfg80211.h>
 #include "ieee80211_i.h"
 #include "driver-ops.h"
@@ -2120,6 +2121,317 @@ static int ieee80211_set_rekey_data(struct wiphy *wiphy,
 	return 0;
 }
 
+static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb)
+{
+	u8 *pos = (void *)skb_put(skb, 7);
+
+	*pos++ = WLAN_EID_EXT_CAPABILITY;
+	*pos++ = 5; /* len */
+	*pos++ = 0x0;
+	*pos++ = 0x0;
+	*pos++ = 0x0;
+	*pos++ = 0x0;
+	*pos++ = WLAN_EXT_CAPA_TDLS_ENABLED;
+}
+
+static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	u16 capab;
+
+	capab = 0;
+	if (local->oper_channel->band != IEEE80211_BAND_2GHZ)
+		return capab;
+
+	if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
+		capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+	if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
+		capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+
+	return capab;
+}
+
+static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr,
+				       u8 *peer, u8 *bssid)
+{
+	struct ieee80211_tdls_lnkie *lnkid;
+
+	lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie));
+
+	lnkid->ie_type = WLAN_EID_LINK_ID;
+	lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2;
+
+	memcpy(lnkid->bssid, bssid, ETH_ALEN);
+	memcpy(lnkid->init_sta, src_addr, ETH_ALEN);
+	memcpy(lnkid->resp_sta, peer, ETH_ALEN);
+}
+
+static int
+ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev,
+			       u8 *peer, u8 action_code, u8 dialog_token,
+			       u16 status_code, struct sk_buff *skb)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_tdls_data *tf;
+
+	tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u));
+
+	memcpy(tf->da, peer, ETH_ALEN);
+	memcpy(tf->sa, sdata->vif.addr, ETH_ALEN);
+	tf->ether_type = cpu_to_be16(ETH_P_TDLS);
+	tf->payload_type = WLAN_TDLS_SNAP_RFTYPE;
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_REQUEST;
+
+		skb_put(skb, sizeof(tf->u.setup_req));
+		tf->u.setup_req.dialog_token = dialog_token;
+		tf->u.setup_req.capability =
+			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
+
+		ieee80211_add_srates_ie(&sdata->vif, skb);
+		ieee80211_add_ext_srates_ie(&sdata->vif, skb);
+		ieee80211_tdls_add_ext_capab(skb);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_RESPONSE;
+
+		skb_put(skb, sizeof(tf->u.setup_resp));
+		tf->u.setup_resp.status_code = cpu_to_le16(status_code);
+		tf->u.setup_resp.dialog_token = dialog_token;
+		tf->u.setup_resp.capability =
+			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
+
+		ieee80211_add_srates_ie(&sdata->vif, skb);
+		ieee80211_add_ext_srates_ie(&sdata->vif, skb);
+		ieee80211_tdls_add_ext_capab(skb);
+		break;
+	case WLAN_TDLS_SETUP_CONFIRM:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_SETUP_CONFIRM;
+
+		skb_put(skb, sizeof(tf->u.setup_cfm));
+		tf->u.setup_cfm.status_code = cpu_to_le16(status_code);
+		tf->u.setup_cfm.dialog_token = dialog_token;
+		break;
+	case WLAN_TDLS_TEARDOWN:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_TEARDOWN;
+
+		skb_put(skb, sizeof(tf->u.teardown));
+		tf->u.teardown.reason_code = cpu_to_le16(status_code);
+		break;
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		tf->category = WLAN_CATEGORY_TDLS;
+		tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST;
+
+		skb_put(skb, sizeof(tf->u.discover_req));
+		tf->u.discover_req.dialog_token = dialog_token;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev,
+			   u8 *peer, u8 action_code, u8 dialog_token,
+			   u16 status_code, struct sk_buff *skb)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_mgmt *mgmt;
+
+	mgmt = (void *)skb_put(skb, 24);
+	memset(mgmt, 0, 24);
+	memcpy(mgmt->da, peer, ETH_ALEN);
+	memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+	memcpy(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN);
+
+	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					  IEEE80211_STYPE_ACTION);
+
+	switch (action_code) {
+	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+		skb_put(skb, 1 + sizeof(mgmt->u.action.u.tdls_discover_resp));
+		mgmt->u.action.category = WLAN_CATEGORY_PUBLIC;
+		mgmt->u.action.u.tdls_discover_resp.action_code =
+			WLAN_PUB_ACTION_TDLS_DISCOVER_RES;
+		mgmt->u.action.u.tdls_discover_resp.dialog_token =
+			dialog_token;
+		mgmt->u.action.u.tdls_discover_resp.capability =
+			cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata));
+
+		ieee80211_add_srates_ie(&sdata->vif, skb);
+		ieee80211_add_ext_srates_ie(&sdata->vif, skb);
+		ieee80211_tdls_add_ext_capab(skb);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
+			       u8 *peer, u8 action_code, u8 dialog_token,
+			       u16 status_code, const u8 *extra_ies,
+			       size_t extra_ies_len)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_tx_info *info;
+	struct sk_buff *skb = NULL;
+	bool send_direct;
+	int ret;
+
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+		return -ENOTSUPP;
+
+	/* make sure we are in managed mode, and associated */
+	if (sdata->vif.type != NL80211_IFTYPE_STATION ||
+	    !sdata->u.mgd.associated)
+		return -EINVAL;
+
+#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG
+	printk(KERN_DEBUG "TDLS mgmt action %d peer %pM\n", action_code, peer);
+#endif
+
+	skb = dev_alloc_skb(local->hw.extra_tx_headroom +
+			    max(sizeof(struct ieee80211_mgmt),
+				sizeof(struct ieee80211_tdls_data)) +
+			    50 + /* supported rates */
+			    7 + /* ext capab */
+			    extra_ies_len +
+			    sizeof(struct ieee80211_tdls_lnkie));
+	if (!skb)
+		return -ENOMEM;
+
+	info = IEEE80211_SKB_CB(skb);
+	skb_reserve(skb, local->hw.extra_tx_headroom);
+
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_RESPONSE:
+	case WLAN_TDLS_SETUP_CONFIRM:
+	case WLAN_TDLS_TEARDOWN:
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		ret = ieee80211_prep_tdls_encap_data(wiphy, dev, peer,
+						     action_code, dialog_token,
+						     status_code, skb);
+		send_direct = false;
+		break;
+	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+		ret = ieee80211_prep_tdls_direct(wiphy, dev, peer, action_code,
+						 dialog_token, status_code,
+						 skb);
+		send_direct = true;
+		break;
+	default:
+		ret = -ENOTSUPP;
+		break;
+	}
+
+	if (ret < 0)
+		goto fail;
+
+	if (extra_ies_len)
+		memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len);
+
+	/* the TDLS link IE is always added last */
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_CONFIRM:
+	case WLAN_TDLS_TEARDOWN:
+	case WLAN_TDLS_DISCOVERY_REQUEST:
+		/* we are the initiator */
+		ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer,
+					   sdata->u.mgd.bssid);
+		break;
+	case WLAN_TDLS_SETUP_RESPONSE:
+	case WLAN_PUB_ACTION_TDLS_DISCOVER_RES:
+		/* we are the responder */
+		ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr,
+					   sdata->u.mgd.bssid);
+		break;
+	default:
+		ret = -ENOTSUPP;
+		goto fail;
+	}
+
+	if (send_direct) {
+		ieee80211_tx_skb(sdata, skb);
+		return 0;
+	}
+
+	/*
+	 * According to 802.11z: Setup req/resp are sent in AC_BK, otherwise
+	 * we should default to AC_VI.
+	 */
+	switch (action_code) {
+	case WLAN_TDLS_SETUP_REQUEST:
+	case WLAN_TDLS_SETUP_RESPONSE:
+		skb_set_queue_mapping(skb, IEEE80211_AC_BK);
+		skb->priority = 2;
+		break;
+	default:
+		skb_set_queue_mapping(skb, IEEE80211_AC_VI);
+		skb->priority = 5;
+		break;
+	}
+
+	/* disable bottom halves when entering the Tx path */
+	local_bh_disable();
+	ret = ieee80211_subif_start_xmit(skb, dev);
+	local_bh_enable();
+
+	return ret;
+
+fail:
+	dev_kfree_skb(skb);
+	return ret;
+}
+
+static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
+			       u8 *peer, enum nl80211_tdls_operation oper)
+{
+	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
+
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
+		return -ENOTSUPP;
+
+	if (sdata->vif.type != NL80211_IFTYPE_STATION)
+		return -EINVAL;
+
+#ifdef CONFIG_MAC80211_VERBOSE_TDLS_DEBUG
+	printk(KERN_DEBUG "TDLS oper %d peer %pM\n", oper, peer);
+#endif
+
+	switch (oper) {
+	case NL80211_TDLS_ENABLE_LINK:
+		break;
+	case NL80211_TDLS_DISABLE_LINK:
+		return sta_info_destroy_addr(sdata, peer);
+	case NL80211_TDLS_TEARDOWN:
+	case NL80211_TDLS_SETUP:
+	case NL80211_TDLS_DISCOVERY_REQ:
+		/* We don't support in-driver setup/teardown/discovery */
+		return -ENOTSUPP;
+	case NL80211_TDLS_DISABLE:
+	case NL80211_TDLS_ENABLE:
+		/* TODO */
+		return -ENOTSUPP;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
 struct cfg80211_ops mac80211_config_ops = {
 	.add_virtual_intf = ieee80211_add_iface,
 	.del_virtual_intf = ieee80211_del_iface,
@@ -2183,4 +2495,6 @@ struct cfg80211_ops mac80211_config_ops = {
 	.set_ringparam = ieee80211_set_ringparam,
 	.get_ringparam = ieee80211_get_ringparam,
 	.set_rekey_data = ieee80211_set_rekey_data,
+	.tdls_oper = ieee80211_tdls_oper,
+	.tdls_mgmt = ieee80211_tdls_mgmt,
 };
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index a5809a1..336ceb9 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -863,6 +863,10 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
 	if (local->ops->sched_scan_start)
 		local->hw.wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
 
+	/* mac80211 based drivers don't support internal TDLS setup */
+	if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
+		local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
+
 	result = wiphy_register(local->hw.wiphy);
 	if (result < 0)
 		goto fail_wiphy_register;
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 4/5] nl80211/mac80211: allow adding TDLS peers as stations
From: Arik Nemtsov @ 2011-09-26 10:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalyan C Gaddam, Arik Nemtsov
In-Reply-To: <1317034493-5300-1-git-send-email-arik@wizery.com>

When adding a TDLS peer STA, mark it with a new flag in both nl80211 and
mac80211. Before adding a peer, make sure the wiphy supports TDLS and
our operating mode is appropriate (managed).

In addition, make sure all peers are removed on disassociation.

A TDLS peer is first added just before link setup is initiated. In later
setup stages we have more info about peer supported rates, capabilities,
etc. This info is reported via nl80211_set_station().

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
---
 include/linux/nl80211.h |    2 ++
 net/mac80211/cfg.c      |   11 +++++++++++
 net/mac80211/mlme.c     |    7 ++++---
 net/mac80211/sta_info.h |    2 ++
 net/wireless/nl80211.c  |   20 +++++++++++++++-----
 5 files changed, 34 insertions(+), 8 deletions(-)

diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 1582916..165a49c 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -1421,6 +1421,7 @@ enum nl80211_iftype {
  * @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
  * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
@@ -1431,6 +1432,7 @@ enum nl80211_sta_flags {
 	NL80211_STA_FLAG_WME,
 	NL80211_STA_FLAG_MFP,
 	NL80211_STA_FLAG_AUTHENTICATED,
+	NL80211_STA_FLAG_TDLS_PEER,
 
 	/* keep last */
 	__NL80211_STA_FLAG_AFTER_LAST,
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 1adf823..8a3168c 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -713,6 +713,12 @@ static void sta_apply_parameters(struct ieee80211_local *local,
 		if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
 			sta->flags |= WLAN_STA_AUTH;
 	}
+
+	if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+		sta->flags &= ~WLAN_STA_TDLS_PEER;
+		if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+			sta->flags |= WLAN_STA_TDLS_PEER;
+	}
 	spin_unlock_irqrestore(&sta->flaglock, flags);
 
 	sta->sta.uapsd_queues = params->uapsd_queues;
@@ -811,6 +817,11 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
 
 	sta_apply_parameters(local, sta, params);
 
+	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
+	    (sta->flags & WLAN_STA_TDLS_PEER)) {
+		return -ENOTSUPP;
+	}
+
 	rate_control_rate_init(sta);
 
 	layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1a59fb6..593a244 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1137,8 +1137,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 	changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
 	ieee80211_bss_info_change_notify(sdata, changed);
 
+	/* remove AP and TDLS peers */
 	if (remove_sta)
-		sta_info_destroy_addr(sdata, bssid);
+		sta_info_flush(local, sdata);
 
 	del_timer_sync(&sdata->u.mgd.conn_mon_timer);
 	del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
@@ -2738,7 +2739,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
 				       req->reason_code, cookie,
 				       !req->local_state_change);
 	if (assoc_bss)
-		sta_info_destroy_addr(sdata, bssid);
+		sta_info_flush(sdata->local, sdata);
 
 	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
@@ -2778,7 +2779,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
 	ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
 			IEEE80211_STYPE_DISASSOC, req->reason_code,
 			cookie, !req->local_state_change);
-	sta_info_destroy_addr(sdata, bssid);
+	sta_info_flush(sdata->local, sdata);
 
 	mutex_lock(&sdata->local->mtx);
 	ieee80211_recalc_idle(sdata->local);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 56a3d38..b6bd4e9 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -45,6 +45,7 @@
  *	station in power-save mode, reply when the driver unblocks.
  * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
  *	buffers. Automatically cleared on station wake-up.
+ * @WLAN_STA_TDLS_PEER: station is a TDLS peer.
  */
 enum ieee80211_sta_info_flags {
 	WLAN_STA_AUTH		= 1<<0,
@@ -61,6 +62,7 @@ enum ieee80211_sta_info_flags {
 	WLAN_STA_PS_DRIVER	= 1<<12,
 	WLAN_STA_PSPOLL		= 1<<13,
 	WLAN_STA_PS_DRIVER_BUF	= 1<<14,
+	WLAN_STA_TDLS_PEER	= 1<<15,
 };
 
 #define STA_TID_NUM 16
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index ed9e6d8..8e5184b 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -2521,18 +2521,18 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)
 		break;
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
-		/* disallow everything but AUTHORIZED flag */
+		/* disallow things sta doesn't support */
 		if (params.plink_action)
 			err = -EINVAL;
 		if (params.vlan)
 			err = -EINVAL;
-		if (params.supported_rates)
-			err = -EINVAL;
 		if (params.ht_capa)
 			err = -EINVAL;
 		if (params.listen_interval >= 0)
 			err = -EINVAL;
-		if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
+		if (params.sta_flags_mask &
+				~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
+				  BIT(NL80211_STA_FLAG_TDLS_PEER)))
 			err = -EINVAL;
 		break;
 	case NL80211_IFTYPE_MESH_POINT:
@@ -2651,7 +2651,17 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)
 	if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
 	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
 	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
-	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO &&
+	    dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
+		return -EINVAL;
+
+	/*
+	 * Managed stations can only add TDLS peers, and only when the
+	 * wiphy supports it.
+	 */
+	if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
+	    (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) ||
+	     !(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS)))
 		return -EINVAL;
 
 	err = get_vlan(info, rdev, &params.vlan);
-- 
1.7.4.1


^ permalink raw reply related

* [PATCH 5/5] mac80211: data path modification for TDLS peers
From: Arik Nemtsov @ 2011-09-26 10:54 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalyan C Gaddam, Arik Nemtsov
In-Reply-To: <1317034493-5300-1-git-send-email-arik@wizery.com>

Mark the STA entries of enabled TDLS peers with a new "peer authorized"
flag.

During link setup, allow special TDLS setup frames through the AP, but
otherwise drop all packets destined to the peer. This is required by the
TDLS (802.11z) specification in order to prevent reordering of MSDUs
between the AP and direct paths.

When setup completes and the peer is authorized, send data directly,
bypassing the AP.

In the Rx path, allow data to be received directly from TDLS peers.

Signed-off-by: Arik Nemtsov <arik@wizery.com>
Cc: Kalyan C Gaddam <chakkal@iit.edu>
---
 net/mac80211/cfg.c      |   10 ++++++++++
 net/mac80211/sta_info.h |    5 ++++-
 net/mac80211/tx.c       |   42 ++++++++++++++++++++++++++++++++++++++----
 net/wireless/util.c     |    5 +++--
 4 files changed, 55 insertions(+), 7 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 8a3168c..729f5c3 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2410,6 +2410,7 @@ fail:
 static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 			       u8 *peer, enum nl80211_tdls_operation oper)
 {
+	struct sta_info *sta;
 	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
 
 	if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS))
@@ -2424,6 +2425,15 @@ static int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
 
 	switch (oper) {
 	case NL80211_TDLS_ENABLE_LINK:
+		rcu_read_lock();
+		sta = sta_info_get(sdata, peer);
+		if (!sta) {
+			rcu_read_unlock();
+			return -ENOLINK;
+		}
+
+		set_sta_flags(sta, WLAN_STA_TDLS_PEER_AUTH);
+		rcu_read_unlock();
 		break;
 	case NL80211_TDLS_DISABLE_LINK:
 		return sta_info_destroy_addr(sdata, peer);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index b6bd4e9..c10e2e8 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -45,7 +45,9 @@
  *	station in power-save mode, reply when the driver unblocks.
  * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
  *	buffers. Automatically cleared on station wake-up.
- * @WLAN_STA_TDLS_PEER: station is a TDLS peer.
+ * @WLAN_STA_TDLS_PEER: Station is a TDLS peer.
+ * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct
+ *	packets. This means the link is enabled.
  */
 enum ieee80211_sta_info_flags {
 	WLAN_STA_AUTH		= 1<<0,
@@ -63,6 +65,7 @@ enum ieee80211_sta_info_flags {
 	WLAN_STA_PSPOLL		= 1<<13,
 	WLAN_STA_PS_DRIVER_BUF	= 1<<14,
 	WLAN_STA_TDLS_PEER	= 1<<15,
+	WLAN_STA_TDLS_PEER_AUTH	= 1<<16,
 };
 
 #define STA_TID_NUM 16
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 542272a..0ca1688 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1726,6 +1726,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 	struct sta_info *sta = NULL;
 	u32 sta_flags = 0;
 	struct sk_buff *tmp_skb;
+	bool tdls_direct = false;
 
 	if (unlikely(skb->len < ETH_HLEN)) {
 		ret = NETDEV_TX_OK;
@@ -1837,11 +1838,43 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 		break;
 #endif
 	case NL80211_IFTYPE_STATION:
-		memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
-		if (sdata->u.mgd.use_4addr &&
-		    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
-			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS);
+		if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) {
+			rcu_read_lock();
+			sta = sta_info_get(sdata, skb->data);
+			if (sta)
+				sta_flags = get_sta_flags(sta);
+			rcu_read_unlock();
+
+			/*
+			 * If the TDLS link is enabled, send everything
+			 * directly. Otherwise, allow TDLS setup frames
+			 * to be transmitted indirectly.
+			 */
+			tdls_direct =
+				(sta_flags & WLAN_STA_TDLS_PEER) &&
+				((sta_flags & WLAN_STA_TDLS_PEER_AUTH) ||
+				 !(ethertype == ETH_P_TDLS && skb->len > 14 &&
+				   skb->data[14] == WLAN_TDLS_SNAP_RFTYPE));
+		}
+
+		if (tdls_direct) {
+			/* link during setup - throw out frames to peer */
+			if (!(sta_flags & WLAN_STA_TDLS_PEER_AUTH)) {
+				ret = NETDEV_TX_OK;
+				goto fail;
+			}
+
+			/* DA SA BSSID */
+			memcpy(hdr.addr1, skb->data, ETH_ALEN);
+			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
+			memcpy(hdr.addr3, sdata->u.mgd.bssid, ETH_ALEN);
+			hdrlen = 24;
+		}  else if (sdata->u.mgd.use_4addr &&
+			    cpu_to_be16(ethertype) != sdata->control_port_protocol) {
+			fc |= cpu_to_le16(IEEE80211_FCTL_FROMDS |
+					  IEEE80211_FCTL_TODS);
 			/* RA TA DA SA */
+			memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
 			memcpy(hdr.addr2, sdata->vif.addr, ETH_ALEN);
 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
 			memcpy(hdr.addr4, skb->data + ETH_ALEN, ETH_ALEN);
@@ -1849,6 +1882,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
 		} else {
 			fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
 			/* BSSID SA DA */
+			memcpy(hdr.addr1, sdata->u.mgd.bssid, ETH_ALEN);
 			memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN);
 			memcpy(hdr.addr3, skb->data, ETH_ALEN);
 			hdrlen = 24;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 39dbf4a..13e6596 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -392,8 +392,9 @@ int ieee80211_data_to_8023(struct sk_buff *skb, const u8 *addr,
 		}
 		break;
 	case cpu_to_le16(0):
-		if (iftype != NL80211_IFTYPE_ADHOC)
-			return -1;
+		if (iftype != NL80211_IFTYPE_ADHOC &&
+		    iftype != NL80211_IFTYPE_STATION)
+				return -1;
 		break;
 	}
 
-- 
1.7.4.1


^ permalink raw reply related

* Re: [RFC] mac80211: Send nullfunc frames at lower rate
From: Stanislaw Gruszka @ 2011-09-26 11:14 UTC (permalink / raw)
  To: Rajkumar Manoharan; +Cc: johannes, linville, linux-wireless
In-Reply-To: <1317030225-3986-1-git-send-email-rmanohar@qca.qualcomm.com>

On Mon, Sep 26, 2011 at 03:13:45PM +0530, Rajkumar Manoharan wrote:
> Recently mac80211 was changed to send nullfunc instead of probe
> request for connection monitoring. These nullfunc data frames
> are being sent at higer rates and also as aggregated ones. This
> could probably delays the nullfunc_ack so the connection is getting
> disconnected as max retries reached. In order to improve the
> connectivity send the nullfunc at lower rate.

We send nullfunc frames for connection monitoring also on older
kernels if hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS. I think
this is -stable fix.

Perhaps also rc_no_data_or_no_ack name should be changed to
something more appropriate.

Stanislaw

^ permalink raw reply

* [RFC v2] mac80211: Send nullfunc frames at lower rate
From: Rajkumar Manoharan @ 2011-09-26 11:14 UTC (permalink / raw)
  To: johannes; +Cc: linville, linux-wireless, Rajkumar Manoharan

Recently mac80211 was changed to use nullfunc instead of probe
request for connection monitoring for tx ack status reporting
hardwares. These nullfunc data frames are being sent at higer
rates and also as aggregated ones. This could probably delays
the nullfunc ack so the connection is more frequently getting
disconnected as max retries are reached. In order to improve
the connectivity send the nullfunc at lower rate.

Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
v2: updated commit log
 net/mac80211/rate.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index f61244c..213e1e9 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -208,7 +208,8 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
 
 	fc = hdr->frame_control;
 
-	return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc);
+	return (info->flags & IEEE80211_TX_CTL_NO_ACK) ||
+		!ieee80211_is_data(fc) || ieee80211_is_nullfunc(fc);
 }
 
 static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
-- 
1.7.6.4


^ permalink raw reply related

* Re: [PATCH] wpa_supplicant: Modify bgscan based roaming behaviour.
From: Jouni Malinen @ 2011-09-26 11:30 UTC (permalink / raw)
  To: Vivek Natarajan; +Cc: hostap, linux-wireless
In-Reply-To: <1314608205-4995-1-git-send-email-nataraja@qca.qualcomm.com>

On Mon, Aug 29, 2011 at 02:26:45PM +0530, Vivek Natarajan wrote:
> Cancel background scan based roaming behavior if the driver
> is capable of handling roaming in the firmware. For fullmac
> drivers like ath6kl, the roaming logic is handled in the
> firmware and for supplicant to initiate roam, the station
> has to disconnect completely and then reconnect with the
> new AP which takes a longer time without preauth.
> 
> Currently, if the supplicant also tries to roam, all requests
> are rejected by cfg80211 resulting in a spam of log.

I applied the driver.h and driver_nl80211.c parts to get the new driver
flag for this, but the change to events.c did not look correct, so I
left that out. wpa_supplicant will need quite a bit more changes to be
able to work in ap_scan=2 like way in the default ap_scan=1 mode when
the driver indicates this BSS-selection-in-driver(firmware) capability.
Those changes will take care of not even getting to the
wpa_supplicant_connect(), so there should be no need to modify it in the
way done in this patch.

-- 
Jouni Malinen                                            PGP id EFC895FA

^ permalink raw reply

* [RFC v3] mac80211: Send nullfunc frames at lower rate
From: Rajkumar Manoharan @ 2011-09-26 12:23 UTC (permalink / raw)
  To: johannes; +Cc: linville, linux-wireless, Rajkumar Manoharan, stable

Recently mac80211 was changed to use nullfunc instead of probe
request for connection monitoring for tx ack status reporting
hardwares. These nullfunc data frames are being sent at higer
rates and also as aggregated ones. This could probably delays
the nullfunc ack so the connection is more frequently getting
disconnected as max retries are reached. In order to improve
the connectivity send the nullfunc at lower rate.

Cc: stable@kernel.org
Signed-off-by: Rajkumar Manoharan <rmanohar@qca.qualcomm.com>
---
v2: update commit log
v3: rename rc_no_data_or_no_ack & Ccd stable
 net/mac80211/rate.c |    7 ++++---
 1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c
index f61244c..240a24d 100644
--- a/net/mac80211/rate.c
+++ b/net/mac80211/rate.c
@@ -199,7 +199,7 @@ static void rate_control_release(struct kref *kref)
 	kfree(ctrl_ref);
 }
 
-static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
+static bool rc_no_non_nulldata_or_no_ack(struct ieee80211_tx_rate_control *txrc)
 {
 	struct sk_buff *skb = txrc->skb;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
@@ -208,7 +208,8 @@ static bool rc_no_data_or_no_ack(struct ieee80211_tx_rate_control *txrc)
 
 	fc = hdr->frame_control;
 
-	return (info->flags & IEEE80211_TX_CTL_NO_ACK) || !ieee80211_is_data(fc);
+	return (info->flags & IEEE80211_TX_CTL_NO_ACK) ||
+		!ieee80211_is_data(fc) || ieee80211_is_nullfunc(fc);
 }
 
 static void rc_send_low_broadcast(s8 *idx, u32 basic_rates,
@@ -262,7 +263,7 @@ bool rate_control_send_low(struct ieee80211_sta *sta,
 	struct ieee80211_supported_band *sband = txrc->sband;
 	int mcast_rate;
 
-	if (!sta || !priv_sta || rc_no_data_or_no_ack(txrc)) {
+	if (!sta || !priv_sta || rc_no_non_nulldata_or_no_ack(txrc)) {
 		if ((sband->band != IEEE80211_BAND_2GHZ) ||
 		    !(info->flags & IEEE80211_TX_CTL_NO_CCK_RATE))
 			info->control.rates[0].idx =
-- 
1.7.6.4


^ permalink raw reply related


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