* mac80211 and kernel 3.8.13 1/2 speed as with madwifi and kernel 2.6.23
From: Beat Meier @ 2013-09-14 20:38 UTC (permalink / raw)
To: linux-wireless
Hello
I'm trying to use again mac driver instead of old madwifi driver for
atheros cards.
I have following problem.
On Clients using mac80211 (wpa_supplicant) it's just fine but if you use
it with hostapd you have about 1/2 speed
as with madwifi. Problem could be also kernel<->wireless driver issue.
With madwifi I'm using an old kernel 2.6.23 (voyage-0.5 distribution)
and with mac80211 a new kernel 3.8.13 (voyage-0.9.1)
Example:
5.5km 5.8GHz link 2xAlix board, 2xWLM54AGP23 card, 2x Hyperlink 27dbi
grids, wireless card speed set to 24M
to get max. signal on this cards...
Signal on both sites is -60
With madwifi driver on both site you get 12.8Mbps/14.5Mbps download/upload
madwifi driver on server, mac80211 on client you still get 13.4/13.8Mbps
BUT if you use mac80211 on ap master mode with hostap you get only
7Mbps/5.5Mbps.
Tried all 4 constellation (old/new, new/old, new/new and old/old) and
the issue is only
if the hostapt is running with new kernel/mac80211
Same stuff on other links with other cards like CM9.
What I have seen is that with madwifi driver the cpu is 90-100% cpu
usage with ksoftirqd
with mac80211 not...
Could this be a kernel interrupt issue? Are there several policies which
changed with kernel?
Anyone having same issue?
Greetings and thanks
^ permalink raw reply
* mac80211 and kernel 3.8.13 1/2 speed as with madwifi and kernel 2.6.23
From: Beat Meier @ 2013-09-14 20:38 UTC (permalink / raw)
To: linux-wireless
Hello
I'm trying to use again mac driver instead of old madwifi driver for
atheros cards.
I have following problem.
On Clients using mac80211 (wpa_supplicant) it's just fine but if you use
it with hostapd you have about 1/2 speed
as with madwifi. Problem could be also kernel<->wireless driver issue.
With madwifi I'm using an old kernel 2.6.23 (voyage-0.5 distribution)
and with mac80211 a new kernel 3.8.13 (voyage-0.9.1)
Example:
5.5km 5.8GHz link 2xAlix board, 2xWLM54AGP23 card, 2x Hyperlink 27dbi
grids, wireless card speed set to 24M
to get max. signal on this cards...
Signal on both sites is -60
With madwifi driver on both site you get 12.8Mbps/14.5Mbps download/upload
madwifi driver on server, mac80211 on client you still get 13.4/13.8Mbps
BUT if you use mac80211 on ap master mode with hostap you get only
7Mbps/5.5Mbps.
Tried all 4 constellation (old/new, new/old, new/new and old/old) and
the issue is only
if the hostapt is running with new kernel/mac80211
Same stuff on other links with other cards like CM9.
What I have seen is that with madwifi driver the cpu is 90-100% cpu
usage with ksoftirqd
with mac80211 not...
Could this be a kernel interrupt issue? Are there several policies which
changed with kernel?
Anyone having same issue?
Greetings and thanks
^ permalink raw reply
* Re: [PATCH 2/7] rtlwifi: rtl8192de: Fix smatch warnings in rtl8192de/hw.c
From: Larry Finger @ 2013-09-14 20:30 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: linville, linux-wireless, netdev
In-Reply-To: <5234C03A.2070701@cogentembedded.com>
On 09/14/2013 02:59 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 09/13/2013 09:44 PM, Larry Finger wrote:
>
>> Smatch lists the following:
>> CHECK drivers/net/wireless/rtlwifi/rtl8192de/hw.c
>> drivers/net/wireless/rtlwifi/rtl8192de/hw.c:1200 rtl92de_set_qos() info:
>> ignoring unreachable code.
>> drivers/net/wireless/rtlwifi/rtl8192de/hw.c:1200 rtl92de_set_qos() info:
>> ignoring unreachable code.
>
>> Dead code is removed.
>
> It is instead commented out, including non-dead code it seems...
>
>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>> ---
>> drivers/net/wireless/rtlwifi/rtl8192de/hw.c | 2 ++
>> 1 file changed, 2 insertions(+)
>>
>> diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
>> b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
>> index 7dd8f6d..c9b0894 100644
>> --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
>> +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
>> @@ -1194,6 +1194,7 @@ void rtl92d_linked_set_reg(struct ieee80211_hw *hw)
>> * mac80211 will send pkt when scan */
>> void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
>> {
>> +/*
>> struct rtl_priv *rtlpriv = rtl_priv(hw);
>> rtl92d_dm_init_edca_turbo(hw);
>> return;
>
> Shouldn't the comment start here (and *return* removed)? It's also
> better to remove the dead code than just to comment it out.
That would leave some unused variables.
>> @@ -1213,6 +1214,7 @@ void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
>> RT_ASSERT(false, "invalid aci: %d !\n", aci);
>> break;
>> }
>> + */
>> }
I'm not sure what that unreachable code might do, thus I saved it as a comment
for possible future use. I need to do further evaluation on this fragment, and
probably consult with the Realtek engineers.
Larry
^ permalink raw reply
* Re: [PATCH 6/7] rtlwifi: Fix smatch warnings in usb.c
From: Larry Finger @ 2013-09-14 20:26 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: linville, linux-wireless, netdev
In-Reply-To: <5234BCB6.6050508@cogentembedded.com>
On 09/14/2013 02:44 PM, Sergei Shtylyov wrote:
> Hello.
>
> On 09/13/2013 09:45 PM, Larry Finger wrote:
>
>> Smatch displays the following:
>> CHECK drivers/net/wireless/rtlwifi/usb.c
>> drivers/net/wireless/rtlwifi/usb.c:458 _rtl_usb_rx_process_agg() warn:
>> assigning (-98) to unsigned variable 'stats.noise'
>> drivers/net/wireless/rtlwifi/usb.c:503 _rtl_usb_rx_process_noagg() warn:
>> assigning (-98) to unsigned variable 'stats.noise'
>> drivers/net/wireless/rtlwifi/usb.c:596 _rtl_rx_get_padding() info: ignoring
>> unreachable code.
>> drivers/net/wireless/rtlwifi/usb.c:596 _rtl_rx_get_padding() info: ignoring
>> unreachable code.
>
>> The negative number to an unsigned quantity is fixed by adding 256 to -98
>> to get the equivalent negative number.
>
>> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
>> ---
>> drivers/net/wireless/rtlwifi/usb.c | 10 +++++++---
>> 1 file changed, 7 insertions(+), 3 deletions(-)
>
>> diff --git a/drivers/net/wireless/rtlwifi/usb.c
>> b/drivers/net/wireless/rtlwifi/usb.c
>> index e56778c..9f3dcb8 100644
>> --- a/drivers/net/wireless/rtlwifi/usb.c
>> +++ b/drivers/net/wireless/rtlwifi/usb.c
> [...]
>> @@ -582,12 +582,15 @@ static void _rtl_rx_work(unsigned long param)
>> static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr,
>> unsigned int len)
>> {
>> +#if NET_IP_ALIGN != 0
>> unsigned int padding = 0;
>> +#endif
>>
>> /* make function no-op when possible */
>> - if (NET_IP_ALIGN == 0 || len < sizeof(*hdr))
>> + if (NET_IP_ALIGN == 0 || len < sizeof(struct ieee80211_hdr))
>
> Why this collateral and undocumented change? What does it achieve?
>
>> return 0;
It does not change a thing. Further up the code is "struct ieee80211_hdr *hdr".
This change was one I tried during the fixes, and I forgot to remove it.
Larry
^ permalink raw reply
* Re: [PATCH 2/7] rtlwifi: rtl8192de: Fix smatch warnings in rtl8192de/hw.c
From: Sergei Shtylyov @ 2013-09-14 19:59 UTC (permalink / raw)
To: Larry Finger; +Cc: linville, linux-wireless, netdev
In-Reply-To: <1379094304-22041-3-git-send-email-Larry.Finger@lwfinger.net>
Hello.
On 09/13/2013 09:44 PM, Larry Finger wrote:
> Smatch lists the following:
> CHECK drivers/net/wireless/rtlwifi/rtl8192de/hw.c
> drivers/net/wireless/rtlwifi/rtl8192de/hw.c:1200 rtl92de_set_qos() info: ignoring unreachable code.
> drivers/net/wireless/rtlwifi/rtl8192de/hw.c:1200 rtl92de_set_qos() info: ignoring unreachable code.
> Dead code is removed.
It is instead commented out, including non-dead code it seems...
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
> drivers/net/wireless/rtlwifi/rtl8192de/hw.c | 2 ++
> 1 file changed, 2 insertions(+)
>
> diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
> index 7dd8f6d..c9b0894 100644
> --- a/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
> +++ b/drivers/net/wireless/rtlwifi/rtl8192de/hw.c
> @@ -1194,6 +1194,7 @@ void rtl92d_linked_set_reg(struct ieee80211_hw *hw)
> * mac80211 will send pkt when scan */
> void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
> {
> +/*
> struct rtl_priv *rtlpriv = rtl_priv(hw);
> rtl92d_dm_init_edca_turbo(hw);
> return;
Shouldn't the comment start here (and *return* removed)? It's also
better to remove the dead code than just to comment it out.
> @@ -1213,6 +1214,7 @@ void rtl92de_set_qos(struct ieee80211_hw *hw, int aci)
> RT_ASSERT(false, "invalid aci: %d !\n", aci);
> break;
> }
> + */
> }
WBR, Sergei
^ permalink raw reply
* Re: [PATCH 6/7] rtlwifi: Fix smatch warnings in usb.c
From: Sergei Shtylyov @ 2013-09-14 19:44 UTC (permalink / raw)
To: Larry Finger; +Cc: linville, linux-wireless, netdev
In-Reply-To: <1379094304-22041-7-git-send-email-Larry.Finger@lwfinger.net>
Hello.
On 09/13/2013 09:45 PM, Larry Finger wrote:
> Smatch displays the following:
> CHECK drivers/net/wireless/rtlwifi/usb.c
> drivers/net/wireless/rtlwifi/usb.c:458 _rtl_usb_rx_process_agg() warn: assigning (-98) to unsigned variable 'stats.noise'
> drivers/net/wireless/rtlwifi/usb.c:503 _rtl_usb_rx_process_noagg() warn: assigning (-98) to unsigned variable 'stats.noise'
> drivers/net/wireless/rtlwifi/usb.c:596 _rtl_rx_get_padding() info: ignoring unreachable code.
> drivers/net/wireless/rtlwifi/usb.c:596 _rtl_rx_get_padding() info: ignoring unreachable code.
> The negative number to an unsigned quantity is fixed by adding 256 to -98
> to get the equivalent negative number.
> Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
> ---
> drivers/net/wireless/rtlwifi/usb.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
> diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c
> index e56778c..9f3dcb8 100644
> --- a/drivers/net/wireless/rtlwifi/usb.c
> +++ b/drivers/net/wireless/rtlwifi/usb.c
[...]
> @@ -582,12 +582,15 @@ static void _rtl_rx_work(unsigned long param)
> static unsigned int _rtl_rx_get_padding(struct ieee80211_hdr *hdr,
> unsigned int len)
> {
> +#if NET_IP_ALIGN != 0
> unsigned int padding = 0;
> +#endif
>
> /* make function no-op when possible */
> - if (NET_IP_ALIGN == 0 || len < sizeof(*hdr))
> + if (NET_IP_ALIGN == 0 || len < sizeof(struct ieee80211_hdr))
Why this collateral and undocumented change? What does it achieve?
> return 0;
WBR, Sergei
^ permalink raw reply
* rtl8192cu: notes on investigating power issues
From: Mark Cave-Ayland @ 2013-09-14 16:09 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless
Hi Larry,
I spent some time yesterday evening adding various debugging statements
around the driver to get a feel for what was happening, with some
success. Included below are my notes from testing.
The key appears to be the calculation of the dig (transmitter gain?)
value, for which the function chain looks like this:
1) rtl92c_dm_ctrl_initgain_by_rssi() sets the dig value
This value controls the power output from the transmitter and should lie
between DM_DIG_MIN and DM_DIG_MAX (note the *higher* the number, the
*lower* the power output). Setting the penultimate line to read
"digtable->cur_igvalue = DM_DIG_MIN" appears to force maximum power and
actually gives me a working connection.
Displaying various values in this function showed that the problem was
that I had an exceptionally high value of digtable->rssi_val_min which
was much higher than DM_DIG_MAX and so had the effect of disabling the
radio.
2) rtl92c_dm_dynamic_bb_powersaving() sets digtable->rssi_val_min
This is actually done by a simple assignment "dm_pstable->rssi_val_min =
rtlpriv->dm.undec_sm_pwdb".
3) _rtl92c_process_pwdb() sets rltpriv->dm.undec_sm_pwdb
This value is updated by comparing the existing value with the current
value of pstats->rx_pwdb_all. If there is a difference, then slide the
new value towards pstats->rx_pwdb_all and then use it to update
rltpriv->dm.undec_sm_pwdb.
4) _rtl92c_query_rxphystatus() sets pstats->rx_pwdb_all
pstats->rx_pwdb_all was set to be a percentage conversion of the current
antenna power read from the radio.
What was happening in my case:
1) pstats->rx_pwdb_all was mostly set to 100 (%) due to high signal strength
2) rltpriv->dm.undec_sm_pwdb would then slide towards a high value
(around 0x40-0x4d) within a few seconds
3) Hence digtable->rssi_val_min would tend to hover at around the same level
4) digtable->cur_igvalue would be set to the same high value (> 0x3f or
DM_DIG_MAX), therefore disabling the radio and disconnecting from the AP
Unfortunately I'm not particularly familiar with these types of power
calculations (and there weren't many comments explaining how they
worked), but the one thing that didn't seem right is that
pstats->rx_pwdb_all claims to be a *percentage* and yet
rtl92c_dm_dynamic_bb_powersaving() uses it as the basis to set the
*value* of dm_pstable->rssi_val_min.
ATB,
Mark.
^ permalink raw reply
* [PATCH 3.12] ath9k: do not link bf_next across multiple A-MPDUs
From: Felix Fietkau @ 2013-09-14 15:02 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
This might trip up tx completion processing, although the condition that
triggers this should not (yet) occur in practice.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/xmit.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a749e0f..5849960 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1951,7 +1951,9 @@ static void ath_tx_txqaddbuf(struct ath_softc *sc, struct ath_txq *txq,
if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth++;
- bf = bf->bf_lastbf->bf_next;
+ bf_last = bf->bf_lastbf;
+ bf = bf_last->bf_next;
+ bf_last->bf_next = NULL;
}
}
}
--
1.8.0.2
^ permalink raw reply related
* Re: guidance on struct alignment for rtl8192cu driver
From: Larry Finger @ 2013-09-14 14:08 UTC (permalink / raw)
To: Jason Andrews; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <985A2B0C3F73B74792F35D4098E1CA7CB143670E93@MAILSJ3.global.cadence.com>
On 09/14/2013 12:36 AM, Jason Andrews wrote:
> I'm using an ASUS USB N13 on an ARM platform with the rtl8192cu driver.
> Linux kernel is 3.10 so I probably don't have the latest and greatest driver.
>
> When I booted I got an ARM alignment trap caused by the driver.
>
> I determined the cause was the 1st argument to spin_lock_irqsave() has an unaligned address.
>
> By trial-and-error I found that if I edit wifi.h and insert 2 dummy bytes into the rtl_priv struct just above priv (last variable) the locks work and the driver works fine.
>
> What is the recommended way to make sure the last variable in the rtl_priv struct (u8 priv[0]) is aligned on a 4 byte boundary so the driver works on ARM machines?
There are a lot of improvements for this driver in 3.11. The backports release
has that code. In addition, I am currently working at improving the power
management for 3.13.
The presence of unaligned variables that cause alignment traps on ARM does not
surprise me as I test only on x86 and ppc architectures. I now own a Raspberry
Pi and I will soon be testing with it as well.
What does surprise me is that the first argument in all the calls to
spin_lock_irqsave() are contained within the rtl_locks struct and everything
there should be aligned. Perhaps some ARM expert will know why aligning the last
item in the rtl_priv struct fixes the problem.
As far as I know, the proper way to do a 4-byte alignment is as in the following
patch:
Index: wireless-testing-save/drivers/net/wireless/rtlwifi/wifi.h
===================================================================
--- wireless-testing-save.orig/drivers/net/wireless/rtlwifi/wifi.h
+++ wireless-testing-save/drivers/net/wireless/rtlwifi/wifi.h
@@ -2057,7 +2057,7 @@ struct rtl_priv {
that it points to the data allocated
beyond this structure like:
rtl_pci_priv or rtl_usb_priv */
- u8 priv[0];
+ u8 __aligned(4) priv[0];
};
#define rtl_priv(hw) (((struct rtl_priv *)(hw)->priv))
Larry
^ permalink raw reply
* [PATCH 3.12] ath9k: fix stale flag handling on buffer clone
From: Felix Fietkau @ 2013-09-14 13:46 UTC (permalink / raw)
To: linux-wireless; +Cc: linville
Fixes a regression from commit
"ath9k: shrink a few data structures by reordering fields"
When cloning a buffer, the stale flag (part of bf_state now) needs to be
reset after copying the state to prevent tx processing hangs.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
---
drivers/net/wireless/ath/ath9k/xmit.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 35b515f..a749e0f 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -399,6 +399,7 @@ static struct ath_buf* ath_clone_txbuf(struct ath_softc *sc, struct ath_buf *bf)
tbf->bf_buf_addr = bf->bf_buf_addr;
memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
tbf->bf_state = bf->bf_state;
+ tbf->bf_state.stale = false;
return tbf;
}
--
1.8.0.2
^ permalink raw reply related
* guidance on struct alignment for rtl8192cu driver
From: Jason Andrews @ 2013-09-14 5:36 UTC (permalink / raw)
To: linux-wireless@vger.kernel.org
I'm using an ASUS USB N13 on an ARM platform with the rtl8192cu driver.
Linux kernel is 3.10 so I probably don't have the latest and greatest driver.
When I booted I got an ARM alignment trap caused by the driver.
I determined the cause was the 1st argument to spin_lock_irqsave() has an unaligned address.
By trial-and-error I found that if I edit wifi.h and insert 2 dummy bytes into the rtl_priv struct just above priv (last variable) the locks work and the driver works fine.
What is the recommended way to make sure the last variable in the rtl_priv struct (u8 priv[0]) is aligned on a 4 byte boundary so the driver works on ARM machines?
Regards,
Jason
^ permalink raw reply
* How to change my current WiFi Driver to ath9k.
From: Abbas Chunawala @ 2013-09-14 5:49 UTC (permalink / raw)
To: linux-wireless
Hi List,
Greetings.
I have a madWiFi Driver
I would like to replace it with ath9k driver.
Which files will i need to remove from the host stack and which will i
have to add.
Particularly there are also files like art.ko ath_hal.ko etc. etc.
By the way i have cross compiled the ath9k driver but the problem lies
that i am not able to figure out the dependencies.
Thanks
Regards
Abbas Chunawala
(System Level Solutions (I) Pvt. Ltd. )
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: btmrvl: add calibration data download support
From: Mike Frysinger @ 2013-09-14 4:04 UTC (permalink / raw)
To: Bing Zhao
Cc: linux-bluetooth, Marcel Holtmann, Gustavo Padovan, Johan Hedberg,
linux-wireless, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <1379115162-10194-1-git-send-email-bzhao@marvell.com>
On Fri, Sep 13, 2013 at 7:32 PM, Bing Zhao wrote:
> --- a/drivers/bluetooth/btmrvl_main.c
> +++ b/drivers/bluetooth/btmrvl_main.c
>
> +static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
would be nice if you put a comment above this func explaining the
expected format. otherwise, we see arbitrary parsing with no idea if
it's correct.
> + while ((s - src) < len) {
> + if (isspace(*s)) {
> + s++;
> + continue;
> + }
> +
> + if (isxdigit(*s)) {
> + if ((d - dst) >= dst_size) {
> + BT_ERR("calibration data file too big!!!");
> + return -EINVAL;
> + }
> +
> + memcpy(tmp, s, 2);
> +
> + ret = kstrtou8(tmp, 16, d++);
> + if (ret < 0)
> + return ret;
> +
> + s += 2;
> + } else {
> + s++;
> + }
> + }
so if it's a space, you skip it. if it's a hexdigit, you parse two
bytes. if it's anything else, you skip it. i'd imagine the "non
space and non hexdigit" case should throw a warning if not reject the
file out right. otherwise, if you want to keep this logic, punt the
explicit "isspace" check.
you might also copy one more byte than you should ? your limit is "(s
- src) < len", yet the isxdigit code always copies two bytes.
> +static int btmrvl_load_cal_data(struct btmrvl_private *priv,
> + u8 *config_data)
> +{
> + struct sk_buff *skb;
> + struct btmrvl_cmd *cmd;
> + int i;
> +
> + skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
maybe i'm unfamiliar with bluetooth and this is common, but why is
your code so special as to require GFP_ATOMIC allocations ?
> + for (i = 4; i < BT_CMD_DATA_SIZE; i++)
> + cmd->data[i] = config_data[(i/4)*8 - 1 - i];
style nit, but there should be spacing around those math operators.
ignoring the fact that this is some funky funky buffer offsets.
i = 4
config_data[(4 / 4) * 8 - 1 - 4] ->
config_data[8 - 1 - 4] ->
config_data[3]
i = 5
config_data[(5 / 4) * 8 - 1 - 5] ->
config_data[8 - 1 - 5] ->
config_data[2]
i = 6
config_data[(6 / 4) * 8 - 1 - 6] ->
config_data[8 - 1 - 6] ->
config_data[1]
i = 7
config_data[(7 / 4) * 8 - 1 - 7] ->
config_data[8 - 1 - 7] ->
config_data[0]
i = 8
config_data[(8 / 4) * 8 - 1 - 8] ->
config_data[16 - 1 - 8] ->
config_data[7]
i = {4,5,6,7} -> config_data[{3,2,1,0}]
i = {8,9,10,11} -> config_data[{7,6,5,4}]
that really could do with a comment explaining the mapping of input
bytes to output bytes.
-mike
^ permalink raw reply
* [PATCH] cw1200: Use a threaded oneshot irq handler for cw1200_spi
From: Solomon Peachy @ 2013-09-14 2:48 UTC (permalink / raw)
To: linux-wireless; +Cc: Solomon Peachy
This supercedes the older patch ("cw1200: Don't perform SPI transfers in
interrupt context") that badly attempted to fix this problem.
This is a far simpler solution, with has the added benefit of actually
working.
Signed-off-by: Solomon Peachy <pizza@shaftnet.org>
---
drivers/net/wireless/cw1200/cw1200_spi.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/cw1200/cw1200_spi.c b/drivers/net/wireless/cw1200/cw1200_spi.c
index 5a64ac9..899cad3 100644
--- a/drivers/net/wireless/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/cw1200/cw1200_spi.c
@@ -250,9 +250,10 @@ static int cw1200_spi_irq_subscribe(struct hwbus_priv *self)
pr_debug("SW IRQ subscribe\n");
- ret = request_any_context_irq(self->func->irq, cw1200_spi_irq_handler,
- IRQF_TRIGGER_HIGH,
- "cw1200_wlan_irq", self);
+ ret = request_threaded_irq(self->func->irq, NULL,
+ cw1200_spi_irq_handler,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "cw1200_wlan_irq", self);
if (WARN_ON(ret < 0))
goto exit;
--
1.8.3.1
^ permalink raw reply related
* Re: [PATCH 1/2] cw1200: Don't perform SPI transfers in interrupt context
From: Solomon Peachy @ 2013-09-14 2:47 UTC (permalink / raw)
To: John W. Linville; +Cc: linux-wireless
In-Reply-To: <20130909183350.GB1955@tuxdriver.com>
[-- Attachment #1: Type: text/plain, Size: 625 bytes --]
On Mon, Sep 09, 2013 at 02:33:50PM -0400, John W. Linville wrote:
> > Since they didn't make it into 3.11, I intend to submit them to -stable,
> > but I need to make sure they at least make it into -next.
>
> I'll be sending them for 3.12 soon...
Can you please revert this commit? (aec8e88c947b7017e2b4bbcb68a4bfc4a1f8ad35)
It ends up creating horrible interrupt losses.
I'll have a much simpler replacement posted shortly.
- Solomon
--
Solomon Peachy pizza at shaftnet dot org
Delray Beach, FL ^^ (email/xmpp) ^^
Quidquid latine dictum sit, altum viditur.
[-- Attachment #2: Type: application/pgp-signature, Size: 190 bytes --]
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: btmrvl: add calibration data download support
From: Marcel Holtmann @ 2013-09-14 1:15 UTC (permalink / raw)
To: Bing Zhao
Cc: linux-bluetooth, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Amitkumar Karwar
In-Reply-To: <1379115162-10194-1-git-send-email-bzhao@marvell.com>
Hi Bing,
> A text file containing calibration data in hex format can
> be provided at following path:
>
> /lib/firmware/mrvl/sd8797_caldata.conf
>
> The data will be downloaded to firmware during initialization.
>
> Reviewed-by: Mike Frysinger <vapier@chromium.org>
> Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
> Signed-off-by: Bing Zhao <bzhao@marvell.com>
> Signed-off-by: Hyuckjoo Lee <hyuckjoo.lee@samsung.com>
> ---
> v2: Remove module parameter. The calibration data will be downloaded
> only when the device speicific data file is provided.
> (Marcel Holtmann)
> v3: Fix crash (misaligned memory access) on ARM
> v4: Simplify white space parsing and save some CPU cycles (Mike Frysinger)
>
> drivers/bluetooth/btmrvl_drv.h | 10 ++-
> drivers/bluetooth/btmrvl_main.c | 140 +++++++++++++++++++++++++++++++++++++++-
> drivers/bluetooth/btmrvl_sdio.c | 9 ++-
> drivers/bluetooth/btmrvl_sdio.h | 2 +
> 4 files changed, 157 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
> index 27068d1..5ef5e84 100644
> --- a/drivers/bluetooth/btmrvl_drv.h
> +++ b/drivers/bluetooth/btmrvl_drv.h
> @@ -23,6 +23,8 @@
> #include <linux/bitops.h>
> #include <linux/slab.h>
> #include <net/bluetooth/bluetooth.h>
> +#include <linux/ctype.h>
> +#include <linux/firmware.h>
>
> #define BTM_HEADER_LEN 4
> #define BTM_UPLD_SIZE 2312
> @@ -41,6 +43,8 @@ struct btmrvl_thread {
> struct btmrvl_device {
> void *card;
> struct hci_dev *hcidev;
> + struct device *dev;
> + const char *cal_data;
>
> u8 dev_type;
>
> @@ -91,6 +95,7 @@ struct btmrvl_private {
> #define BT_CMD_HOST_SLEEP_CONFIG 0x59
> #define BT_CMD_HOST_SLEEP_ENABLE 0x5A
> #define BT_CMD_MODULE_CFG_REQ 0x5B
> +#define BT_CMD_LOAD_CONFIG_DATA 0x61
>
> /* Sub-commands: Module Bringup/Shutdown Request/Response */
> #define MODULE_BRINGUP_REQ 0xF1
> @@ -116,10 +121,13 @@ struct btmrvl_private {
> #define PS_SLEEP 0x01
> #define PS_AWAKE 0x00
>
> +#define BT_CMD_DATA_SIZE 32
> +#define BT_CAL_DATA_SIZE 28
> +
> struct btmrvl_cmd {
> __le16 ocf_ogf;
> u8 length;
> - u8 data[4];
> + u8 data[BT_CMD_DATA_SIZE];
> } __packed;
>
> struct btmrvl_event {
> diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
> index 9a9f518..77e940e 100644
> --- a/drivers/bluetooth/btmrvl_main.c
> +++ b/drivers/bluetooth/btmrvl_main.c
> @@ -57,8 +57,9 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
> ocf = hci_opcode_ocf(opcode);
> ogf = hci_opcode_ogf(opcode);
>
> - if (ocf == BT_CMD_MODULE_CFG_REQ &&
> - priv->btmrvl_dev.sendcmdflag) {
> + if ((ocf == BT_CMD_MODULE_CFG_REQ ||
> + ocf == BT_CMD_LOAD_CONFIG_DATA) &&
> + priv->btmrvl_dev.sendcmdflag) {
> priv->btmrvl_dev.sendcmdflag = false;
> priv->adapter->cmd_complete = true;
> wake_up_interruptible(&priv->adapter->cmd_wait_q);
> @@ -552,6 +553,132 @@ static int btmrvl_service_main_thread(void *data)
> return 0;
> }
>
> +static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
> +{
> + const u8 *s = src;
> + u8 *d = dst;
> + int ret;
> + u8 tmp[3];
> +
> + tmp[2] = '\0';
> + while ((s - src) < len) {
> + if (isspace(*s)) {
> + s++;
> + continue;
> + }
> +
> + if (isxdigit(*s)) {
> + if ((d - dst) >= dst_size) {
> + BT_ERR("calibration data file too big!!!");
> + return -EINVAL;
> + }
> +
> + memcpy(tmp, s, 2);
> +
> + ret = kstrtou8(tmp, 16, d++);
> + if (ret < 0)
> + return ret;
> +
> + s += 2;
> + } else {
> + s++;
> + }
> + }
> + if (d == dst)
> + return -EINVAL;
> +
> + return 0;
> +}
> +
> +static int btmrvl_load_cal_data(struct btmrvl_private *priv,
> + u8 *config_data)
> +{
> + struct sk_buff *skb;
> + struct btmrvl_cmd *cmd;
> + int i;
> +
> + skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
> + if (!skb)
> + return -ENOMEM;
> +
> + cmd = (struct btmrvl_cmd *)skb->data;
> + cmd->ocf_ogf =
> + cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_LOAD_CONFIG_DATA));
> + cmd->length = BT_CMD_DATA_SIZE;
> + cmd->data[0] = 0x00;
> + cmd->data[1] = 0x00;
> + cmd->data[2] = 0x00;
> + cmd->data[3] = BT_CMD_DATA_SIZE - 4;
> +
> + /* swap cal-data bytes */
> + for (i = 4; i < BT_CMD_DATA_SIZE; i++)
> + cmd->data[i] = config_data[(i/4)*8 - 1 - i];
> +
> + bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
> + skb_put(skb, sizeof(*cmd));
> + skb->dev = (void *)priv->btmrvl_dev.hcidev;
> + skb_queue_head(&priv->adapter->tx_queue, skb);
> + priv->btmrvl_dev.sendcmdflag = true;
> + priv->adapter->cmd_complete = false;
since the Bluetooth HCI core got ->setup() support with proper synchronous HCI request handling available for every single driver (see the Intel support in btusb.c), why not start using that with this driver as well.
Regards
Marcel
^ permalink raw reply
* [PATCH v4] Bluetooth: btmrvl: add calibration data download support
From: Bing Zhao @ 2013-09-13 23:32 UTC (permalink / raw)
To: linux-bluetooth
Cc: Marcel Holtmann, Gustavo Padovan, Johan Hedberg, linux-wireless,
Mike Frysinger, Hyuckjoo Lee, Bing Zhao, Amitkumar Karwar
From: Amitkumar Karwar <akarwar@marvell.com>
A text file containing calibration data in hex format can
be provided at following path:
/lib/firmware/mrvl/sd8797_caldata.conf
The data will be downloaded to firmware during initialization.
Reviewed-by: Mike Frysinger <vapier@chromium.org>
Signed-off-by: Amitkumar Karwar <akarwar@marvell.com>
Signed-off-by: Bing Zhao <bzhao@marvell.com>
Signed-off-by: Hyuckjoo Lee <hyuckjoo.lee@samsung.com>
---
v2: Remove module parameter. The calibration data will be downloaded
only when the device speicific data file is provided.
(Marcel Holtmann)
v3: Fix crash (misaligned memory access) on ARM
v4: Simplify white space parsing and save some CPU cycles (Mike Frysinger)
drivers/bluetooth/btmrvl_drv.h | 10 ++-
drivers/bluetooth/btmrvl_main.c | 140 +++++++++++++++++++++++++++++++++++++++-
drivers/bluetooth/btmrvl_sdio.c | 9 ++-
drivers/bluetooth/btmrvl_sdio.h | 2 +
4 files changed, 157 insertions(+), 4 deletions(-)
diff --git a/drivers/bluetooth/btmrvl_drv.h b/drivers/bluetooth/btmrvl_drv.h
index 27068d1..5ef5e84 100644
--- a/drivers/bluetooth/btmrvl_drv.h
+++ b/drivers/bluetooth/btmrvl_drv.h
@@ -23,6 +23,8 @@
#include <linux/bitops.h>
#include <linux/slab.h>
#include <net/bluetooth/bluetooth.h>
+#include <linux/ctype.h>
+#include <linux/firmware.h>
#define BTM_HEADER_LEN 4
#define BTM_UPLD_SIZE 2312
@@ -41,6 +43,8 @@ struct btmrvl_thread {
struct btmrvl_device {
void *card;
struct hci_dev *hcidev;
+ struct device *dev;
+ const char *cal_data;
u8 dev_type;
@@ -91,6 +95,7 @@ struct btmrvl_private {
#define BT_CMD_HOST_SLEEP_CONFIG 0x59
#define BT_CMD_HOST_SLEEP_ENABLE 0x5A
#define BT_CMD_MODULE_CFG_REQ 0x5B
+#define BT_CMD_LOAD_CONFIG_DATA 0x61
/* Sub-commands: Module Bringup/Shutdown Request/Response */
#define MODULE_BRINGUP_REQ 0xF1
@@ -116,10 +121,13 @@ struct btmrvl_private {
#define PS_SLEEP 0x01
#define PS_AWAKE 0x00
+#define BT_CMD_DATA_SIZE 32
+#define BT_CAL_DATA_SIZE 28
+
struct btmrvl_cmd {
__le16 ocf_ogf;
u8 length;
- u8 data[4];
+ u8 data[BT_CMD_DATA_SIZE];
} __packed;
struct btmrvl_event {
diff --git a/drivers/bluetooth/btmrvl_main.c b/drivers/bluetooth/btmrvl_main.c
index 9a9f518..77e940e 100644
--- a/drivers/bluetooth/btmrvl_main.c
+++ b/drivers/bluetooth/btmrvl_main.c
@@ -57,8 +57,9 @@ bool btmrvl_check_evtpkt(struct btmrvl_private *priv, struct sk_buff *skb)
ocf = hci_opcode_ocf(opcode);
ogf = hci_opcode_ogf(opcode);
- if (ocf == BT_CMD_MODULE_CFG_REQ &&
- priv->btmrvl_dev.sendcmdflag) {
+ if ((ocf == BT_CMD_MODULE_CFG_REQ ||
+ ocf == BT_CMD_LOAD_CONFIG_DATA) &&
+ priv->btmrvl_dev.sendcmdflag) {
priv->btmrvl_dev.sendcmdflag = false;
priv->adapter->cmd_complete = true;
wake_up_interruptible(&priv->adapter->cmd_wait_q);
@@ -552,6 +553,132 @@ static int btmrvl_service_main_thread(void *data)
return 0;
}
+static int btmrvl_parse_cal_cfg(const u8 *src, u32 len, u8 *dst, u32 dst_size)
+{
+ const u8 *s = src;
+ u8 *d = dst;
+ int ret;
+ u8 tmp[3];
+
+ tmp[2] = '\0';
+ while ((s - src) < len) {
+ if (isspace(*s)) {
+ s++;
+ continue;
+ }
+
+ if (isxdigit(*s)) {
+ if ((d - dst) >= dst_size) {
+ BT_ERR("calibration data file too big!!!");
+ return -EINVAL;
+ }
+
+ memcpy(tmp, s, 2);
+
+ ret = kstrtou8(tmp, 16, d++);
+ if (ret < 0)
+ return ret;
+
+ s += 2;
+ } else {
+ s++;
+ }
+ }
+ if (d == dst)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int btmrvl_load_cal_data(struct btmrvl_private *priv,
+ u8 *config_data)
+{
+ struct sk_buff *skb;
+ struct btmrvl_cmd *cmd;
+ int i;
+
+ skb = bt_skb_alloc(sizeof(*cmd), GFP_ATOMIC);
+ if (!skb)
+ return -ENOMEM;
+
+ cmd = (struct btmrvl_cmd *)skb->data;
+ cmd->ocf_ogf =
+ cpu_to_le16(hci_opcode_pack(OGF, BT_CMD_LOAD_CONFIG_DATA));
+ cmd->length = BT_CMD_DATA_SIZE;
+ cmd->data[0] = 0x00;
+ cmd->data[1] = 0x00;
+ cmd->data[2] = 0x00;
+ cmd->data[3] = BT_CMD_DATA_SIZE - 4;
+
+ /* swap cal-data bytes */
+ for (i = 4; i < BT_CMD_DATA_SIZE; i++)
+ cmd->data[i] = config_data[(i/4)*8 - 1 - i];
+
+ bt_cb(skb)->pkt_type = MRVL_VENDOR_PKT;
+ skb_put(skb, sizeof(*cmd));
+ skb->dev = (void *)priv->btmrvl_dev.hcidev;
+ skb_queue_head(&priv->adapter->tx_queue, skb);
+ priv->btmrvl_dev.sendcmdflag = true;
+ priv->adapter->cmd_complete = false;
+
+ print_hex_dump_bytes("Calibration data: ",
+ DUMP_PREFIX_OFFSET, cmd->data, BT_CMD_DATA_SIZE);
+
+ wake_up_interruptible(&priv->main_thread.wait_q);
+ if (!wait_event_interruptible_timeout(priv->adapter->cmd_wait_q,
+ priv->adapter->cmd_complete,
+ msecs_to_jiffies(WAIT_UNTIL_CMD_RESP))) {
+ BT_ERR("Timeout while loading calibration data");
+ return -ETIMEDOUT;
+ }
+
+ return 0;
+}
+
+static int
+btmrvl_process_cal_cfg(struct btmrvl_private *priv, u8 *data, u32 size)
+{
+ u8 cal_data[BT_CAL_DATA_SIZE];
+ int ret;
+
+ ret = btmrvl_parse_cal_cfg(data, size, cal_data, sizeof(cal_data));
+ if (ret)
+ return ret;
+
+ ret = btmrvl_load_cal_data(priv, cal_data);
+ if (ret) {
+ BT_ERR("Fail to load calibrate data");
+ return ret;
+ }
+
+ return 0;
+}
+
+static int btmrvl_cal_data_config(struct btmrvl_private *priv)
+{
+ const struct firmware *cfg;
+ int ret;
+ const char *cal_data = priv->btmrvl_dev.cal_data;
+
+ if (!cal_data)
+ return 0;
+
+ ret = request_firmware(&cfg, cal_data, priv->btmrvl_dev.dev);
+ if (ret < 0) {
+ BT_DBG("Failed to get %s file, skipping cal data download",
+ cal_data);
+ ret = 0;
+ goto done;
+ }
+
+ ret = btmrvl_process_cal_cfg(priv, (u8 *)cfg->data, cfg->size);
+done:
+ if (cfg)
+ release_firmware(cfg);
+
+ return ret;
+}
+
int btmrvl_register_hdev(struct btmrvl_private *priv)
{
struct hci_dev *hdev = NULL;
@@ -583,12 +710,21 @@ int btmrvl_register_hdev(struct btmrvl_private *priv)
goto err_hci_register_dev;
}
+ ret = btmrvl_cal_data_config(priv);
+ if (ret) {
+ BT_ERR("Set cal data failed");
+ goto err_cal_data_config;
+ }
+
#ifdef CONFIG_DEBUG_FS
btmrvl_debugfs_init(hdev);
#endif
return 0;
+err_cal_data_config:
+ hci_unregister_dev(hdev);
+
err_hci_register_dev:
hci_free_dev(hdev);
diff --git a/drivers/bluetooth/btmrvl_sdio.c b/drivers/bluetooth/btmrvl_sdio.c
index 00da6df..af7f48d 100644
--- a/drivers/bluetooth/btmrvl_sdio.c
+++ b/drivers/bluetooth/btmrvl_sdio.c
@@ -18,7 +18,6 @@
* this warranty disclaimer.
**/
-#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/mmc/sdio_ids.h>
@@ -102,6 +101,7 @@ static const struct btmrvl_sdio_card_reg btmrvl_reg_88xx = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
.helper = "mrvl/sd8688_helper.bin",
.firmware = "mrvl/sd8688.bin",
+ .cal_data = NULL,
.reg = &btmrvl_reg_8688,
.sd_blksz_fw_dl = 64,
};
@@ -109,6 +109,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8688 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
.helper = NULL,
.firmware = "mrvl/sd8787_uapsta.bin",
+ .cal_data = NULL,
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
@@ -116,6 +117,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8787 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
.helper = NULL,
.firmware = "mrvl/sd8797_uapsta.bin",
+ .cal_data = "mrvl/sd8797_caldata.conf",
.reg = &btmrvl_reg_87xx,
.sd_blksz_fw_dl = 256,
};
@@ -123,6 +125,7 @@ static const struct btmrvl_sdio_device btmrvl_sdio_sd8797 = {
static const struct btmrvl_sdio_device btmrvl_sdio_sd8897 = {
.helper = NULL,
.firmware = "mrvl/sd8897_uapsta.bin",
+ .cal_data = NULL,
.reg = &btmrvl_reg_88xx,
.sd_blksz_fw_dl = 256,
};
@@ -1006,6 +1009,7 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
struct btmrvl_sdio_device *data = (void *) id->driver_data;
card->helper = data->helper;
card->firmware = data->firmware;
+ card->cal_data = data->cal_data;
card->reg = data->reg;
card->sd_blksz_fw_dl = data->sd_blksz_fw_dl;
}
@@ -1034,6 +1038,8 @@ static int btmrvl_sdio_probe(struct sdio_func *func,
}
card->priv = priv;
+ priv->btmrvl_dev.dev = &card->func->dev;
+ priv->btmrvl_dev.cal_data = card->cal_data;
/* Initialize the interface specific function pointers */
priv->hw_host_to_card = btmrvl_sdio_host_to_card;
@@ -1222,4 +1228,5 @@ MODULE_FIRMWARE("mrvl/sd8688_helper.bin");
MODULE_FIRMWARE("mrvl/sd8688.bin");
MODULE_FIRMWARE("mrvl/sd8787_uapsta.bin");
MODULE_FIRMWARE("mrvl/sd8797_uapsta.bin");
+MODULE_FIRMWARE("mrvl/sd8797_caldata.conf");
MODULE_FIRMWARE("mrvl/sd8897_uapsta.bin");
diff --git a/drivers/bluetooth/btmrvl_sdio.h b/drivers/bluetooth/btmrvl_sdio.h
index 43d35a6..6872d9e 100644
--- a/drivers/bluetooth/btmrvl_sdio.h
+++ b/drivers/bluetooth/btmrvl_sdio.h
@@ -85,6 +85,7 @@ struct btmrvl_sdio_card {
u32 ioport;
const char *helper;
const char *firmware;
+ const char *cal_data;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
u8 rx_unit;
@@ -94,6 +95,7 @@ struct btmrvl_sdio_card {
struct btmrvl_sdio_device {
const char *helper;
const char *firmware;
+ const char *cal_data;
const struct btmrvl_sdio_card_reg *reg;
u16 sd_blksz_fw_dl;
};
--
1.8.0
^ permalink raw reply related
* [PATCH 5/5] mac80211: process mesh channel switching using beacon
From: Chun-Yeow Yeoh @ 2013-09-13 23:36 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville, devel, distro11s, Chun-Yeow Yeoh
In-Reply-To: <1379115372-28426-1-git-send-email-yeohchunyeow@cozybit.com>
Trigger the mesh channel switching procedure if the mesh STA
happens to miss the CSA action frame but able to receive the
beacon containing the CSA and MCSP elements from its peer
mesh STAs.
Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com>
---
net/mac80211/ibss.c | 4 +-
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/mesh.c | 129 +++++++++++++++++++++++++++++++++++++++++---
net/mac80211/mlme.c | 4 +-
net/mac80211/spectmgmt.c | 8 ++-
5 files changed, 134 insertions(+), 13 deletions(-)
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 017e206..a29f969 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -736,7 +736,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
enum nl80211_channel_type ch_type;
int err, num_chanctx;
u32 sta_flags;
- u8 mode;
+ u8 mode, ttl;
if (sdata->vif.csa_active)
return true;
@@ -762,7 +762,7 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon,
ifibss->chandef.chan->band,
sta_flags, ifibss->bssid,
- ¶ms.count, &mode,
+ ¶ms.count, &mode, &ttl,
¶ms.chandef);
/* can't switch to destination channel, fail */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 48da719..fb24ad9 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1510,6 +1510,7 @@ void ieee80211_process_measurement_req(struct ieee80211_sub_if_data *sdata,
* @count: to be filled with the counter until the switch (on success only)
* @bssid: the currently connected bssid (for reporting)
* @mode: to be filled with CSA mode (on success only)
+ * @ttl: to be filled with mesh TTL related to channel switch
* @new_chandef: to be filled with destination chandef (on success only)
* Return: 0 on success, <0 on error and >0 if there is nothing to parse.
*/
@@ -1517,6 +1518,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon,
enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid, u8 *count, u8 *mode,
+ u8 *ttl,
struct cfg80211_chan_def *new_chandef);
/* Suspend/resume and hw reconfiguration */
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 2f756dd..180c898 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -847,6 +847,121 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
ieee80211_configure_filter(local);
}
+static bool
+ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
+ struct ieee802_11_elems *elems, bool beacon)
+{
+ struct cfg80211_csa_settings params;
+ struct ieee80211_chanctx_conf *chanctx_conf;
+ struct ieee80211_chanctx *chanctx;
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+ int err, num_chanctx;
+ u32 sta_flags;
+ u8 mode, ttl;
+
+ if (sdata->vif.csa_active)
+ return true;
+
+ if (!ifmsh->mesh_id)
+ return false;
+
+ sta_flags = IEEE80211_STA_DISABLE_VHT;
+ switch (sdata->vif.bss_conf.chandef.width) {
+ case NL80211_CHAN_WIDTH_20_NOHT:
+ sta_flags |= IEEE80211_STA_DISABLE_HT;
+ case NL80211_CHAN_WIDTH_20:
+ sta_flags |= IEEE80211_STA_DISABLE_40MHZ;
+ break;
+ default:
+ break;
+ }
+
+ memset(¶ms, 0, sizeof(params));
+ err = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, band,
+ sta_flags, sdata->vif.addr,
+ ¶ms.count, &mode, &ttl,
+ ¶ms.chandef);
+
+ if (err < 0)
+ return false;
+ if (err)
+ return false;
+
+ if (sdata->vif.bss_conf.chandef.chan->band !=
+ params.chandef.chan->band)
+ return false;
+
+ if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef,
+ IEEE80211_CHAN_DISABLED)) {
+ sdata_info(sdata,
+ "mesh STA %pM switches to unsupported channel (%d MHz, width:%d, CF1/2: %d/%d MHz), aborting\n",
+ sdata->vif.addr,
+ params.chandef.chan->center_freq,
+ params.chandef.width,
+ params.chandef.center_freq1,
+ params.chandef.center_freq2);
+ }
+
+ err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy,
+ ¶ms.chandef);
+ if (err < 0)
+ return false;
+ if (err) {
+ params.radar_required = true;
+ /* TODO: DFS not (yet) supported */
+ return false;
+ }
+
+ rcu_read_lock();
+ chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+ if (!chanctx_conf)
+ goto failed_chswitch;
+
+ /* don't handle for multi-VIF cases */
+ chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
+ if (chanctx->refcount > 1)
+ goto failed_chswitch;
+
+ num_chanctx = 0;
+ list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
+ num_chanctx++;
+
+ if (num_chanctx > 1)
+ goto failed_chswitch;
+
+ rcu_read_unlock();
+
+ mcsa_dbg(sdata,
+ "received channel switch announcement to go to channel %d MHz\n",
+ params.chandef.chan->center_freq);
+
+ params.block_tx = !!(mode & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT);
+ if (beacon)
+ ifmsh->chsw_ttl = ttl - 1;
+
+ if (ifmsh->chsw_ttl > 0)
+ ieee80211_mesh_csa_beacon(sdata, ¶ms, false);
+
+ sdata->csa_radar_required = params.radar_required;
+
+ if (params.block_tx)
+ ieee80211_stop_queues_by_reason(&sdata->local->hw,
+ IEEE80211_MAX_QUEUE_MAP,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+
+ sdata->local->csa_chandef = params.chandef;
+ sdata->vif.csa_active = true;
+
+ ieee80211_bss_info_change_notify(sdata, err);
+ drv_channel_switch_beacon(sdata, ¶ms.chandef);
+
+ return true;
+failed_chswitch:
+ rcu_read_unlock();
+ return false;
+}
+
static void
ieee80211_mesh_rx_probe_req(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len)
@@ -953,6 +1068,9 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
if (ifmsh->sync_ops)
ifmsh->sync_ops->rx_bcn_presp(sdata,
stype, mgmt, &elems, rx_status);
+
+ if (!ifmsh->chsw_init)
+ ieee80211_mesh_process_chnswitch(sdata, &elems, true);
}
int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
@@ -1047,7 +1165,7 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee802_11_elems elems;
u16 pre_value;
- bool block_tx, fwd_csa = true;
+ bool fwd_csa = true;
size_t baselen;
u8 *pos, ttl;
@@ -1076,13 +1194,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
mcsa_dbg(sdata, "Failed to forward the CSA frame");
}
- /* block the Tx only after fowarding the CSA frame if required */
- block_tx = !!(elems.mesh_chansw_params_ie->mesh_flags
- & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT);
- if (block_tx)
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
- IEEE80211_MAX_QUEUE_MAP,
- IEEE80211_QUEUE_STOP_REASON_CSA);
+ if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false))
+ mcsa_dbg(sdata, "Failed to process CSA action frame");
}
static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 9fce0f4..83e6609 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -942,7 +942,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_chanctx *chanctx;
enum ieee80211_band current_band;
u8 count;
- u8 mode;
+ u8 mode, ttl;
struct cfg80211_chan_def new_chandef = {};
int res;
@@ -962,7 +962,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
res = ieee80211_parse_ch_switch_ie(sdata, elems, beacon, current_band,
ifmgd->flags,
ifmgd->associated->bssid, &count,
- &mode, &new_chandef);
+ &mode, &ttl, &new_chandef);
if (res < 0)
ieee80211_queue_work(&local->hw,
&ifmgd->csa_connection_drop_work);
diff --git a/net/mac80211/spectmgmt.c b/net/mac80211/spectmgmt.c
index 921597e..0762676 100644
--- a/net/mac80211/spectmgmt.c
+++ b/net/mac80211/spectmgmt.c
@@ -25,7 +25,7 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems *elems, bool beacon,
enum ieee80211_band current_band,
u32 sta_flags, u8 *bssid, u8 *count, u8 *mode,
- struct cfg80211_chan_def *new_chandef)
+ u8 *ttl, struct cfg80211_chan_def *new_chandef)
{
enum ieee80211_band new_band;
int new_freq;
@@ -74,6 +74,12 @@ int ieee80211_parse_ch_switch_ie(struct ieee80211_sub_if_data *sdata,
return 1;
}
+ /* Mesh Channel Switch Parameters Element */
+ if (elems->mesh_chansw_params_ie) {
+ *ttl = elems->mesh_chansw_params_ie->mesh_ttl;
+ *mode = elems->mesh_chansw_params_ie->mesh_flags;
+ }
+
new_freq = ieee80211_channel_to_frequency(new_chan_no, new_band);
new_chan = ieee80211_get_channel(sdata->local->hw.wiphy, new_freq);
if (!new_chan || new_chan->flags & IEEE80211_CHAN_DISABLED) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH 4/5] {nl,cfg,mac}80211: finalizing mesh channel switching
From: Chun-Yeow Yeoh @ 2013-09-13 23:36 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville, devel, distro11s, Chun-Yeow Yeoh
In-Reply-To: <1379115372-28426-1-git-send-email-yeohchunyeow@cozybit.com>
Finalizing the requried procedures for channel switching completion and
also adding the function for updating the beacon and probe response frames
with CSA and MCSP elements. Once the channel switching is completed, the
CSA and MCSP elements are removed from the beacon or probe response frames
as defined in the IEEE Std 802.11-2012 section 10.9.8.4.3.
Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com>
---
net/mac80211/cfg.c | 7 +++++-
net/mac80211/ieee80211_i.h | 4 ++++
net/mac80211/mesh.c | 54 ++++++++++++++++++++++++++++++++++++++++++++
net/mac80211/rx.c | 5 +++-
net/mac80211/tx.c | 16 +++++++++++++
net/wireless/nl80211.c | 3 ++-
6 files changed, 86 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 438c689..a0b41d7 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2887,6 +2887,11 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
case NL80211_IFTYPE_ADHOC:
ieee80211_ibss_finish_csa(sdata);
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ err = ieee80211_mesh_finish_csa(sdata);
+ if (err < 0)
+ return;
+ break;
default:
WARN_ON(1);
return;
@@ -3005,7 +3010,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->band)
return -EINVAL;
- err = ieee80211_send_action_csa(sdata, params);
+ err = ieee80211_mesh_csa_beacon(sdata, params, true);
if (err < 0)
return err;
break;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index f10907f..48da719 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1345,6 +1345,10 @@ void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata);
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);
+int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *csa_settings,
+ bool csa_action);
+int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata);
/* scan/BSS handling */
void ieee80211_scan_work(struct work_struct *work);
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index a839ab9..2f756dd 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -12,6 +12,7 @@
#include <asm/unaligned.h>
#include "ieee80211_i.h"
#include "mesh.h"
+#include "driver-ops.h"
static int mesh_allocated;
static struct kmem_cache *rm_cache;
@@ -954,6 +955,59 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
stype, mgmt, &elems, rx_status);
}
+int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ int ret = 0;
+
+ /* Remove the CSA and MCSP elements from the beacon */
+ kfree(ifmsh->csa_settings);
+ ifmsh->csa_settings = NULL;
+ ret = ieee80211_mesh_rebuild_beacon(sdata);
+ if (ret)
+ return -EINVAL;
+
+ /* Reset the TTL value and Initiator flag */
+ ifmsh->chsw_init = false;
+ ifmsh->chsw_ttl = 0;
+
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
+
+ mcsa_dbg(sdata, "complete switching to center freq %d MHz",
+ sdata->vif.bss_conf.chandef.chan->center_freq);
+ return ret;
+}
+
+int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *csa_settings,
+ bool csa_action)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct cfg80211_csa_settings *tmp_csa_settings;
+ int ret = 0;
+
+ if (csa_action)
+ ieee80211_send_action_csa(sdata, csa_settings);
+
+ tmp_csa_settings = kmalloc(sizeof(struct cfg80211_csa_settings),
+ GFP_ATOMIC);
+ if (!tmp_csa_settings) {
+ mcsa_dbg(sdata, "could not allocate memory for csa beaconing");
+ return -ENOMEM;
+ }
+
+ ifmsh->csa_settings = tmp_csa_settings;
+ memcpy(ifmsh->csa_settings, csa_settings,
+ sizeof(struct cfg80211_csa_settings));
+
+ ret = ieee80211_mesh_rebuild_beacon(sdata);
+ if (ret)
+ return -EINVAL;
+
+ ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
+ return ret;
+}
+
static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt, size_t len)
{
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 8e908e1..0ba1fad 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -2592,13 +2592,16 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
break;
if (sdata->vif.type != NL80211_IFTYPE_STATION &&
- sdata->vif.type != NL80211_IFTYPE_ADHOC)
+ sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
break;
if (sdata->vif.type == NL80211_IFTYPE_STATION)
bssid = sdata->u.mgd.bssid;
else if (sdata->vif.type == NL80211_IFTYPE_ADHOC)
bssid = sdata->u.ibss.bssid;
+ else if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
+ bssid = mgmt->sa;
else
break;
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 4fcbf63..80b9a57 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2369,6 +2369,10 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
beacon_data = beacon->head;
beacon_data_len = beacon->head_len;
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ beacon_data = beacon->head;
+ beacon_data_len = beacon->head_len;
+ break;
default:
return;
}
@@ -2425,6 +2429,15 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
beacon_data = beacon->head;
beacon_data_len = beacon->head_len;
+ } else if (vif->type == NL80211_IFTYPE_MESH_POINT) {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+
+ beacon = rcu_dereference(ifmsh->beacon);
+ if (!beacon)
+ goto out;
+
+ beacon_data = beacon->head;
+ beacon_data_len = beacon->head_len;
} else {
WARN_ON(1);
goto out;
@@ -2530,6 +2543,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw,
if (!bcn)
goto out;
+ if (sdata->vif.csa_active)
+ ieee80211_update_csa(sdata, bcn);
+
if (ifmsh->sync_ops)
ifmsh->sync_ops->adjust_tbtt(
sdata);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 7bb5aca..be844d4 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -10760,7 +10760,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev,
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO &&
- wdev->iftype != NL80211_IFTYPE_ADHOC))
+ wdev->iftype != NL80211_IFTYPE_ADHOC &&
+ wdev->iftype != NL80211_IFTYPE_MESH_POINT))
goto out;
wdev->channel = chandef->chan;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 3/5] mac80211: adding the CSA and MCSP elements in mesh beaconing
From: Chun-Yeow Yeoh @ 2013-09-13 23:36 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville, devel, distro11s, Chun-Yeow Yeoh
In-Reply-To: <1379115372-28426-1-git-send-email-yeohchunyeow@cozybit.com>
Support the adding of CSA and MCSP elements while building the beacon
for mesh if necessary. This is defined in the IEEE Std 802.11-2012
section 10.9.8.4.3 that both CSA and MCSP elements must be included
in beacon and probe response frames until the intended channel
switch time.
Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com>
---
net/mac80211/ieee80211_i.h | 2 ++
net/mac80211/mesh.c | 35 +++++++++++++++++++++++++++++++++++
2 files changed, 37 insertions(+)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 829ff7e..f10907f 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -599,7 +599,9 @@ struct ieee80211_if_mesh {
int ps_peers_deep_sleep;
struct ps_data ps;
/* Channel Switching Support */
+ struct cfg80211_csa_settings *csa_settings;
bool chsw_init;
+ u8 chsw_ttl;
u16 pre_value;
};
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 308ef98..a839ab9 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -624,6 +624,10 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
head_len = hdr_len +
2 + /* NULL SSID */
+ /* Channel Switch Announcement */
+ 2 + sizeof(struct ieee80211_channel_sw_ie) +
+ /* Mesh Channel Swith Parameters */
+ 2 + sizeof(struct ieee80211_mesh_chansw_params_ie) +
2 + 8 + /* supported rates */
2 + 3; /* DS params */
tail_len = 2 + (IEEE80211_MAX_SUPP_RATES - 8) +
@@ -665,6 +669,36 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
*pos++ = WLAN_EID_SSID;
*pos++ = 0x0;
+ if (ifmsh->csa_settings) {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ __le16 pre_value;
+
+ pos = skb_put(skb, 13);
+ memset(pos, 0, 13);
+ *pos++ = WLAN_EID_CHANNEL_SWITCH;
+ *pos++ = 3;
+ *pos++ = 0x0;
+ *pos++ = ieee80211_frequency_to_channel(
+ ifmsh->csa_settings->chandef.chan->center_freq);
+ sdata->csa_counter_offset_beacon = hdr_len + 6;
+ *pos++ = ifmsh->csa_settings->count;
+ *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
+ *pos++ = 6;
+ if (ifmsh->chsw_init) {
+ *pos++ = ifmsh->mshcfg.dot11MeshTTL;
+ *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
+ } else {
+ *pos++ = ifmsh->chsw_ttl;
+ }
+ *pos++ |= ifmsh->csa_settings->block_tx ?
+ WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
+ put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos);
+ pos += 2;
+ pre_value = cpu_to_le16(ifmsh->pre_value);
+ memcpy(pos, &pre_value, 2);
+ pos += 2;
+ }
+
if (ieee80211_add_srates_ie(sdata, skb, true, band) ||
mesh_add_ds_params_ie(sdata, skb))
goto out_free;
@@ -942,6 +976,7 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
offset_ttl = (len < 42) ? 7 : 10;
*(pos + offset_ttl) -= 1;
*(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
+ sdata->u.mesh.chsw_ttl = *(pos + offset_ttl);
memcpy(mgmt_fwd, mgmt, len);
eth_broadcast_addr(mgmt_fwd->da);
--
1.7.9.5
^ permalink raw reply related
* [PATCH 2/5] {nl,cfg,mac}80211: enable the triggering of CSA frame in mesh
From: Chun-Yeow Yeoh @ 2013-09-13 23:36 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville, devel, distro11s, Chun-Yeow Yeoh
In-Reply-To: <1379115372-28426-1-git-send-email-yeohchunyeow@cozybit.com>
Allow the triggering of CSA frame using mesh interface. The
rules are more or less same with IBSS, such as not allowed to
change between the band and channel width has to be same from
the previous mode. Also, move the ieee80211_send_action_csa
to a common space so that it can be re-used by mesh interface.
Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com>
---
net/mac80211/cfg.c | 19 ++++++++++
net/mac80211/ibss.c | 54 ---------------------------
net/mac80211/ieee80211_i.h | 2 +
net/mac80211/util.c | 88 ++++++++++++++++++++++++++++++++++++++++++++
net/wireless/nl80211.c | 1 +
5 files changed, 110 insertions(+), 54 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index b455e72..438c689 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2907,6 +2907,7 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_chanctx *chanctx;
+ struct ieee80211_if_mesh *ifmsh;
int err, num_chanctx;
if (!list_empty(&local->roc_list) || local->scanning)
@@ -2990,6 +2991,24 @@ static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
if (err < 0)
return err;
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ ifmsh = &sdata->u.mesh;
+
+ if (!ifmsh->mesh_id)
+ return -EINVAL;
+
+ if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
+ return -EINVAL;
+
+ /* changes into another band are not supported */
+ if (sdata->vif.bss_conf.chandef.chan->band !=
+ params->chandef.chan->band)
+ return -EINVAL;
+
+ err = ieee80211_send_action_csa(sdata, params);
+ if (err < 0)
+ return err;
+ break;
default:
return -EOPNOTSUPP;
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 5ea9b3a..017e206 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -428,60 +428,6 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
tsf, false);
}
-static int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_csa_settings *csa_settings)
-{
- struct sk_buff *skb;
- struct ieee80211_mgmt *mgmt;
- struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- struct ieee80211_local *local = sdata->local;
- int freq;
- int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) +
- sizeof(mgmt->u.action.u.chan_switch);
- u8 *pos;
-
- skb = dev_alloc_skb(local->tx_headroom + hdr_len +
- 5 + /* channel switch announcement element */
- 3); /* secondary channel offset element */
- if (!skb)
- return -1;
-
- skb_reserve(skb, local->tx_headroom);
- mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len);
- memset(mgmt, 0, hdr_len);
- mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
- IEEE80211_STYPE_ACTION);
-
- eth_broadcast_addr(mgmt->da);
- memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
- memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
- mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
- mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
- pos = skb_put(skb, 5);
- *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */
- *pos++ = 3; /* IE length */
- *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */
- freq = csa_settings->chandef.chan->center_freq;
- *pos++ = ieee80211_frequency_to_channel(freq); /* channel */
- *pos++ = csa_settings->count; /* count */
-
- if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) {
- enum nl80211_channel_type ch_type;
-
- skb_put(skb, 3);
- *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
- *pos++ = 1; /* IE length */
- ch_type = cfg80211_get_chandef_type(&csa_settings->chandef);
- if (ch_type == NL80211_CHAN_HT40PLUS)
- *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
- else
- *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
- }
-
- ieee80211_tx_skb(sdata, skb);
- return 0;
-}
-
int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings *csa_settings)
{
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 7f13b65..829ff7e 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1714,6 +1714,8 @@ void ieee80211_dfs_cac_timer(unsigned long data);
void ieee80211_dfs_cac_timer_work(struct work_struct *work);
void ieee80211_dfs_cac_cancel(struct ieee80211_local *local);
void ieee80211_dfs_radar_detected_work(struct work_struct *work);
+int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *csa_settings);
#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 133667c..c013cc4 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2361,3 +2361,91 @@ u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c)
return ret;
}
+
+int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
+ struct cfg80211_csa_settings *csa_settings)
+{
+ struct sk_buff *skb;
+ struct ieee80211_mgmt *mgmt;
+ struct ieee80211_local *local = sdata->local;
+ int freq;
+ int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.chan_switch) +
+ sizeof(mgmt->u.action.u.chan_switch);
+ u8 *pos;
+
+ if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
+ sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
+ return -EOPNOTSUPP;
+
+ skb = dev_alloc_skb(local->tx_headroom + hdr_len +
+ 5 + /* channel switch announcement element */
+ 3 + /* secondary channel offset element */
+ 8); /* mesh channel switch parameters element */
+ if (!skb)
+ return -1;
+
+ skb_reserve(skb, local->tx_headroom);
+ mgmt = (struct ieee80211_mgmt *)skb_put(skb, hdr_len);
+ memset(mgmt, 0, hdr_len);
+ mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+ IEEE80211_STYPE_ACTION);
+
+ eth_broadcast_addr(mgmt->da);
+ memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
+ memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
+ } else {
+ struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
+ memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
+ }
+ mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
+ mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
+ pos = skb_put(skb, 5);
+ *pos++ = WLAN_EID_CHANNEL_SWITCH; /* EID */
+ *pos++ = 3; /* IE length */
+ *pos++ = csa_settings->block_tx ? 1 : 0; /* CSA mode */
+ freq = csa_settings->chandef.chan->center_freq;
+ *pos++ = ieee80211_frequency_to_channel(freq); /* channel */
+ *pos++ = csa_settings->count; /* count */
+
+ if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) {
+ enum nl80211_channel_type ch_type;
+
+ skb_put(skb, 3);
+ *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET; /* EID */
+ *pos++ = 1; /* IE length */
+ ch_type = cfg80211_get_chandef_type(&csa_settings->chandef);
+ if (ch_type == NL80211_CHAN_HT40PLUS)
+ *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+ else
+ *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+ }
+
+ if (ieee80211_vif_is_mesh(&sdata->vif)) {
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ __le16 pre_value;
+
+ skb_put(skb, 8);
+ *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; /* EID */
+ *pos++ = 6; /* IE length */
+ *pos++ = sdata->u.mesh.mshcfg.dot11MeshTTL; /* Mesh TTL */
+ *pos = 0x00; /* Mesh Flag: Tx Restrict, Initiator, Reason */
+ *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
+ *pos++ |= csa_settings->block_tx ?
+ WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
+ put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
+ pos += 2;
+ if (!ifmsh->pre_value)
+ ifmsh->pre_value = 1;
+ else
+ ifmsh->pre_value++;
+ pre_value = cpu_to_le16(ifmsh->pre_value);
+ memcpy(pos, &pre_value, 2); /* Precedence Value */
+ pos += 2;
+ ifmsh->chsw_init = true;
+ }
+
+ ieee80211_tx_skb(sdata, skb);
+ return 0;
+}
+
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index da8de5b..7bb5aca 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -5650,6 +5650,7 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info)
return -EINVAL;
break;
case NL80211_IFTYPE_ADHOC:
+ case NL80211_IFTYPE_MESH_POINT:
break;
default:
return -EOPNOTSUPP;
--
1.7.9.5
^ permalink raw reply related
* [PATCH 1/5] mac80211: process the CSA frame for mesh accordingly
From: Chun-Yeow Yeoh @ 2013-09-13 23:36 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville, devel, distro11s, Chun-Yeow Yeoh
In-Reply-To: <1379115372-28426-1-git-send-email-yeohchunyeow@cozybit.com>
Process the CSA frame according to the procedures define in IEEE Std
802.11-2012 section 10.9.8.4.3 as follow:
* The mesh channel switch parameters element (MCSP) must be availabe.
* If the MCSP's TTL is 1, drop the frame but still process the CSA.
* If the MCSP's precedence value is less than or equal to the current
precedence value, drop the frame and do not process the CSA.
* The CSA frame is forwarded after TTL is decremented by 1 and the
initiator field is set to 0. Transmit restrict field and others
are maintained as is.
* No beacon or probe response frame are handled here.
Also, introduce the debug message used for mesh CSA purpose.
Signed-off-by: Chun-Yeow Yeoh <yeohchunyeow@cozybit.com>
---
include/linux/ieee80211.h | 20 +++++++++++
net/mac80211/Kconfig | 11 ++++++
net/mac80211/debug.h | 10 ++++++
net/mac80211/ieee80211_i.h | 4 +++
net/mac80211/mesh.c | 83 ++++++++++++++++++++++++++++++++++++++++++--
net/mac80211/util.c | 9 +++++
6 files changed, 134 insertions(+), 3 deletions(-)
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index 23a8877..f117427 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -696,6 +696,18 @@ struct ieee80211_sec_chan_offs_ie {
} __packed;
/**
+ * struct ieee80211_mesh_chansw_params_ie - mesh channel switch parameters IE
+ *
+ * This structure represents the "Mesh Channel Switch Paramters element"
+ */
+struct ieee80211_mesh_chansw_params_ie {
+ u8 mesh_ttl;
+ u8 mesh_flags;
+ __le16 mesh_reason;
+ __le16 mesh_pre_value;
+} __packed;
+
+/**
* struct ieee80211_wide_bw_chansw_ie - wide bandwidth channel switch IE
*/
struct ieee80211_wide_bw_chansw_ie {
@@ -750,6 +762,14 @@ enum mesh_config_capab_flags {
};
/**
+ * mesh channel switch parameters element's flag indicator
+ *
+ */
+#define WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT BIT(0)
+#define WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR BIT(1)
+#define WLAN_EID_CHAN_SWITCH_PARAM_REASON BIT(2)
+
+/**
* struct ieee80211_rann_ie
*
* This structure refers to "Root Announcement information element"
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig
index 62535fe..bf1871e 100644
--- a/net/mac80211/Kconfig
+++ b/net/mac80211/Kconfig
@@ -258,6 +258,17 @@ config MAC80211_MESH_SYNC_DEBUG
Do not select this option.
+config MAC80211_MESH_CSA_DEBUG
+ bool "Verbose mesh channel switch debugging"
+ depends on MAC80211_DEBUG_MENU
+ depends on MAC80211_MESH
+ ---help---
+ Selecting this option causes mac80211 to print out very verbose mesh
+ channel switch debugging messages (when mac80211 is taking part in a
+ mesh network).
+
+ Do not select this option.
+
config MAC80211_MESH_PS_DEBUG
bool "Verbose mesh powersave debugging"
depends on MAC80211_DEBUG_MENU
diff --git a/net/mac80211/debug.h b/net/mac80211/debug.h
index 4ccc5ed..493d680 100644
--- a/net/mac80211/debug.h
+++ b/net/mac80211/debug.h
@@ -44,6 +44,12 @@
#define MAC80211_MESH_SYNC_DEBUG 0
#endif
+#ifdef CONFIG_MAC80211_MESH_CSA_DEBUG
+#define MAC80211_MESH_CSA_DEBUG 1
+#else
+#define MAC80211_MESH_CSA_DEBUG 0
+#endif
+
#ifdef CONFIG_MAC80211_MESH_PS_DEBUG
#define MAC80211_MESH_PS_DEBUG 1
#else
@@ -157,6 +163,10 @@ do { \
_sdata_dbg(MAC80211_MESH_SYNC_DEBUG, \
sdata, fmt, ##__VA_ARGS__)
+#define mcsa_dbg(sdata, fmt, ...) \
+ _sdata_dbg(MAC80211_MESH_CSA_DEBUG, \
+ sdata, fmt, ##__VA_ARGS__)
+
#define mps_dbg(sdata, fmt, ...) \
_sdata_dbg(MAC80211_MESH_PS_DEBUG, \
sdata, fmt, ##__VA_ARGS__)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3a87c89..7f13b65 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -598,6 +598,9 @@ struct ieee80211_if_mesh {
int ps_peers_light_sleep;
int ps_peers_deep_sleep;
struct ps_data ps;
+ /* Channel Switching Support */
+ bool chsw_init;
+ u16 pre_value;
};
#ifdef CONFIG_MAC80211_MESH
@@ -1239,6 +1242,7 @@ struct ieee802_11_elems {
const struct ieee80211_timeout_interval_ie *timeout_int;
const u8 *opmode_notif;
const struct ieee80211_sec_chan_offs_ie *sec_chan_offs;
+ const struct ieee80211_mesh_chansw_params_ie *mesh_chansw_params_ie;
/* length of them, respectively */
u8 ssid_len;
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 707ac61..308ef98 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -920,6 +920,82 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
stype, mgmt, &elems, rx_status);
}
+static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
+{
+ struct ieee80211_mgmt *mgmt_fwd;
+ struct sk_buff *skb;
+ struct ieee80211_local *local = sdata->local;
+ u8 *pos = mgmt->u.action.u.chan_switch.variable;
+ size_t offset_ttl;
+
+ skb = dev_alloc_skb(local->tx_headroom + len);
+ if (!skb)
+ return -1;
+ skb_reserve(skb, local->tx_headroom);
+ mgmt_fwd = (struct ieee80211_mgmt *) skb_put(skb, len);
+
+ /* offset_ttl is based on whether the secondary channel
+ * offset is available or not. Substract 1 from the mesh TTL
+ * and disable the initiator flag before forwarding.
+ */
+ offset_ttl = (len < 42) ? 7 : 10;
+ *(pos + offset_ttl) -= 1;
+ *(pos + offset_ttl + 1) &= ~WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
+
+ memcpy(mgmt_fwd, mgmt, len);
+ eth_broadcast_addr(mgmt_fwd->da);
+ memcpy(mgmt_fwd->sa, sdata->vif.addr, ETH_ALEN);
+ memcpy(mgmt_fwd->bssid, sdata->vif.addr, ETH_ALEN);
+
+ ieee80211_tx_skb(sdata, skb);
+ return 0;
+}
+
+static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
+{
+ struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
+ struct ieee802_11_elems elems;
+ u16 pre_value;
+ bool block_tx, fwd_csa = true;
+ size_t baselen;
+ u8 *pos, ttl;
+
+ if (mgmt->u.action.u.measurement.action_code !=
+ WLAN_ACTION_SPCT_CHL_SWITCH)
+ return;
+
+ pos = mgmt->u.action.u.chan_switch.variable;
+ baselen = offsetof(struct ieee80211_mgmt,
+ u.action.u.chan_switch.variable);
+ ieee802_11_parse_elems(pos, len - baselen, false, &elems);
+
+ ttl = elems.mesh_chansw_params_ie->mesh_ttl;
+ if (!--ttl)
+ fwd_csa = false;
+
+ pre_value = le16_to_cpu(elems.mesh_chansw_params_ie->mesh_pre_value);
+ if (ifmsh->pre_value >= pre_value)
+ return;
+
+ ifmsh->pre_value = pre_value;
+
+ /* forward or re-broadcast the CSA frame */
+ if (fwd_csa) {
+ if (mesh_fwd_csa_frame(sdata, mgmt, len) < 0)
+ mcsa_dbg(sdata, "Failed to forward the CSA frame");
+ }
+
+ /* block the Tx only after fowarding the CSA frame if required */
+ block_tx = !!(elems.mesh_chansw_params_ie->mesh_flags
+ & WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT);
+ if (block_tx)
+ ieee80211_stop_queues_by_reason(&sdata->local->hw,
+ IEEE80211_MAX_QUEUE_MAP,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
+}
+
static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
struct ieee80211_mgmt *mgmt,
size_t len,
@@ -939,6 +1015,9 @@ static void ieee80211_mesh_rx_mgmt_action(struct ieee80211_sub_if_data *sdata,
if (mesh_action_is_path_sel(mgmt))
mesh_rx_path_sel_frame(sdata, mgmt, len);
break;
+ case WLAN_CATEGORY_SPECTRUM_MGMT:
+ mesh_rx_csa_frame(sdata, mgmt, len);
+ break;
}
}
@@ -1056,13 +1135,11 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
(unsigned long) sdata);
ifmsh->accepting_plinks = true;
- ifmsh->preq_id = 0;
- ifmsh->sn = 0;
- ifmsh->num_gates = 0;
atomic_set(&ifmsh->mpaths, 0);
mesh_rmc_init(sdata);
ifmsh->last_preq = jiffies;
ifmsh->next_perr = jiffies;
+ ifmsh->chsw_init = false;
/* Allocate all mesh structures when creating the first mesh interface. */
if (!mesh_allocated)
ieee80211s_init();
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 3c8283b..133667c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -743,6 +743,7 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
case WLAN_EID_TIMEOUT_INTERVAL:
case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
+ case WLAN_EID_CHAN_SWITCH_PARAM:
/*
* not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
* that if the content gets bigger it might be needed more than once
@@ -908,6 +909,14 @@ u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
}
elems->sec_chan_offs = (void *)pos;
break;
+ case WLAN_EID_CHAN_SWITCH_PARAM:
+ if (elen !=
+ sizeof(*elems->mesh_chansw_params_ie)) {
+ elem_parse_failed = true;
+ break;
+ }
+ elems->mesh_chansw_params_ie = (void *)pos;
+ break;
case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
if (!action ||
elen != sizeof(*elems->wide_bw_chansw_ie)) {
--
1.7.9.5
^ permalink raw reply related
* [PATCH 0/5] Add Mesh Channel Switch Support
From: Chun-Yeow Yeoh @ 2013-09-13 23:36 UTC (permalink / raw)
To: linux-wireless; +Cc: johannes, linville, devel, distro11s, Chun-Yeow Yeoh
These are the patches required to support Mesh Basic Service Set (MBSS)
channel switch.
The design is more or less same with the IBSS. Additional procedures
or elements that are required for mesh operation are as follow:
* Add additional information element (IE) known as Mesh Channel Switch
Parameters (MCSP) required in CSA action, beacon and probe response
frames.
* Forwarding of CSA frame if the conditions defined in the standard
are met.
Limitations:
* Channel switch is only allow for the same band and also same channel
width from the previous setting.
These patches are reviewed and commented by Bob Copeland and Thomas
Pedersen. Any further comments are welcomed.
Chun-Yeow Yeoh (5):
mac80211: process the CSA frame for mesh accordingly
{nl,cfg,mac}80211: enable the triggering of CSA frame in mesh
mac80211: adding the CSA and MCSP elements in mesh beaconing
{nl,cfg,mac}80211: finalizing mesh channel switching
mac80211: process mesh channel switching using beacon
include/linux/ieee80211.h | 20 ++++
net/mac80211/Kconfig | 11 ++
net/mac80211/cfg.c | 24 ++++
net/mac80211/debug.h | 10 ++
net/mac80211/ibss.c | 58 +--------
net/mac80211/ieee80211_i.h | 14 +++
net/mac80211/mesh.c | 284 +++++++++++++++++++++++++++++++++++++++++++-
net/mac80211/mlme.c | 4 +-
net/mac80211/rx.c | 5 +-
net/mac80211/spectmgmt.c | 8 +-
net/mac80211/tx.c | 16 +++
net/mac80211/util.c | 97 +++++++++++++++
net/wireless/nl80211.c | 4 +-
13 files changed, 491 insertions(+), 64 deletions(-)
--
1.7.9.5
^ permalink raw reply
* Re: rtl8192cu: testing with EdiMax USB
From: Mark Cave-Ayland @ 2013-09-13 18:20 UTC (permalink / raw)
To: Larry Finger; +Cc: linux-wireless
In-Reply-To: <523352C8.8000902@lwfinger.net>
On 13/09/13 19:00, Larry Finger wrote:
> Thanks for the info. Eliminating the call to rtl92c_dm_diginit() is a
> very large hammer to attack a small flea, but that points to a potential
> problem.
Glad that it proves useful to you. If you need me to run test patches
(e.g. logging calculated power values to dmesg), please send them
through to me off-list and I'll run them and send you back the results.
Given that it could be related to power calculations, another bit of
information that may help you recreate this is that my desk is really
close to the AP (probably 10m or a bit less), and so the indicated
signal strength should be close to maximum.
HTH,
Mark.
^ permalink raw reply
* Re: rtl8192cu: testing with EdiMax USB
From: Larry Finger @ 2013-09-13 18:00 UTC (permalink / raw)
To: Mark Cave-Ayland; +Cc: linux-wireless
In-Reply-To: <523312D0.3020001@ilande.co.uk>
On 09/13/2013 08:27 AM, Mark Cave-Ayland wrote:
> On 13/09/13 14:01, Mark Cave-Ayland wrote:
>
>>> I spent a bit more time tinkering further with debug=0x5, forgetting
>>> that I had left your last diagnostic patch applied. Based upon when the
>>> beacon output disappears in the logs (after updating the power
>>> registers), it does seem likely that is a power-related problem.
>>
>> FWIW I just tried a quick test where I commented out the entire
>> rtl92c_dm_txpower_tracking_callback_thermalmeter() function to make it a
>> nop, and that didn't seem to make any difference...
>
> Aha! The following diff to remove the call to rtl92c_dm_diginit() keeps me
> associated to the AP:
>
> diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
> b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
> index d2d57a2..c18362d 100644
> --- a/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
> +++ b/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
> @@ -1275,7 +1275,7 @@ void rtl92c_dm_init(struct ieee80211_hw *hw)
> struct rtl_priv *rtlpriv = rtl_priv(hw);
>
> rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
> - rtl92c_dm_diginit(hw);
> + //rtl92c_dm_diginit(hw);
> rtl92c_dm_init_dynamic_txpower(hw);
> rtl92c_dm_init_edca_turbo(hw);
> rtl92c_dm_init_rate_adaptive_mask(hw);
>
> However, dhclient still takes a very long time get an IP address and the
> connection seems extremely lossy, much like it was when I could get a connection
> before. Perhaps there are two different bugs here, one for the association and
> one for the data loss?
Thanks for the info. Eliminating the call to rtl92c_dm_diginit() is a very large
hammer to attack a small flea, but that points to a potential problem.
Larry
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox