* Re: [PATCH v2] ath10k: cache calibration data when the core is stopped
From: Valo, Kalle @ 2016-10-10 15:59 UTC (permalink / raw)
To: Marty Faltesek; +Cc: ath10k@lists.infradead.org, linux-wireless@vger.kernel.org
In-Reply-To: <CAOiWkA8yX6bnLWHTwMc21EJHh4tQHpdBH+yKL4Y9WWxufBKaKQ@mail.gmail.com>
Marty Faltesek <mfaltesek@google.com> writes:
> ath10k: cache calibration data when the core is stopped
>
> Caching calibration data allows it to be accessed when the
> device is not active.
>
> Signed-off-by: Marty Faltesek <mfaltesek@google.com>
Thanks, I'll now send v3.
--=20
Kalle Valo=
^ permalink raw reply
* Re: [mac80211] BUG_ON with current -git (4.8.0-11417-g24532f7)
From: Sergey Senozhatsky @ 2016-10-10 15:30 UTC (permalink / raw)
To: Sergey Senozhatsky
Cc: Andy Lutomirski, David S. Miller, Johannes Berg, linux-wireless,
netdev, linux-kernel, Sergey Senozhatsky, linux-next,
Stephen Rothwell
In-Reply-To: <20161010150358.GA514@swordfish>
Cc Andy
Andy, can this be related to CONFIG_VMAP_STACK?
On (10/11/16 00:03), Sergey Senozhatsky wrote:
> Hello,
>
> current -git kills my system. adding
>
> if (!virt_addr_valid(&aad[2])) {
> WARN_ON(1);
> return -EINVAL;
> }
>
> to ieee80211_aes_ccm_decrypt() given the following backtrace
>
> WARNING: CPU: 5 PID: 252 at net/mac80211/aes_ccm.c:77 ieee80211_aes_ccm_decrypt+0xc8/0x197
> CPU: 5 PID: 252 Comm: irq/29-iwlwifi Tainted: G W 4.8.0-next-20161010-dbg-00007-g79797e9-dirty #88
> ffffc90000413638 ffffffff811ff0e3 0000000000000000 0000000000000000
> ffffc90000413678 ffffffff8103fe91 0000004d000001c8 1ffff920000826d3
> ffff88040fc526d8 0000000000000008 ffffc90000413978 ffffc9000041397a
> Call Trace:
> [<ffffffff811ff0e3>] dump_stack+0x4f/0x65
> [<ffffffff8103fe91>] __warn+0xc2/0xdd
> [<ffffffff8103ff1c>] warn_slowpath_null+0x1d/0x1f
> [<ffffffff8142aaa5>] ieee80211_aes_ccm_decrypt+0xc8/0x197
> [<ffffffff810ed595>] ? __put_page+0x3c/0x3f
> [<ffffffff8131fa42>] ? put_page+0x4a/0x62
> [<ffffffff813218d3>] ? __pskb_pull_tail+0x1e8/0x279
> [<ffffffff8141a7dc>] ? ccmp_special_blocks.isra.5+0x51/0x12d
> [<ffffffff8141b226>] ieee80211_crypto_ccmp_decrypt+0x1ba/0x221
> [<ffffffff81432e80>] ieee80211_rx_handlers+0x52a/0x19c2
> [<ffffffff81070000>] ? start_dl_timer+0xa8/0xb4
> [<ffffffff8107462d>] ? put_lock_stats.isra.24+0xe/0x20
> [<ffffffff8108ebec>] ? del_timer+0x57/0x61
> [<ffffffff814351a8>] ieee80211_prepare_and_rx_handle+0xcd6/0xd2a
> [<ffffffff810742a5>] ? local_clock+0x10/0x12
> [<ffffffff8107642b>] ? __lock_acquire.isra.31+0x202/0x57e
> [<ffffffff8143207b>] ? rcu_read_unlock+0x23/0x23
> [<ffffffff81066e77>] ? sched_clock_cpu+0x17/0xc6
> [<ffffffff814357ab>] ieee80211_rx_napi+0x5af/0x698
> [<ffffffff810742c0>] ? get_lock_stats+0x19/0x50
> [<ffffffff8107462d>] ? put_lock_stats.isra.24+0xe/0x20
> [<ffffffffa023aaa9>] iwl_mvm_rx_rx_mpdu+0x5ab/0x60c [iwlmvm]
> [<ffffffff810742c0>] ? get_lock_stats+0x19/0x50
> [<ffffffffa0235c80>] iwl_mvm_rx+0x45/0x69 [iwlmvm]
> [<ffffffffa01a989e>] iwl_pcie_rx_handle+0x478/0x584 [iwlwifi]
> [<ffffffffa01aaafd>] iwl_pcie_irq_handler+0x39c/0x52d [iwlwifi]
> [<ffffffff81080824>] ? irq_finalize_oneshot+0xa7/0xa7
> [<ffffffff81080841>] irq_thread_fn+0x1d/0x34
> [<ffffffff81080ab5>] irq_thread+0xe6/0x1bb
> [<ffffffff8108093a>] ? wake_threads_waitq+0x2c/0x2c
> [<ffffffff810809cf>] ? irq_thread_dtor+0x95/0x95
> [<ffffffff81059d79>] kthread+0xc6/0xce
> [<ffffffff8107462d>] ? put_lock_stats.isra.24+0xe/0x20
> [<ffffffff81059cb3>] ? __list_del_entry+0x22/0x22
> [<ffffffff814669d2>] ret_from_fork+0x22/0x30
> ---[ end trace 94da6d4698b938b2 ]---
-ss
^ permalink raw reply
* [PATCH] Revert "rtlwifi: rtl818x: constify local structures"
From: Larry Finger @ 2016-10-10 15:25 UTC (permalink / raw)
To: kvalo; +Cc: devel, linux-wireless, Larry Finger, Stable, Julia Lawall
This reverts commit d86e64768859fca82c78e52877ceeba04e25d27a.
For drivers rtl8188ee, rtl8192ce, rtl8192ee, rtl8723ae, and rtl8821ae,
the Coccinelle script missed the fact that the code changes the firmware
name. When that happens, the kernel issues a BUG splat because
it is unable to overwrite the old name.
Although this bug only affects 5 of the 8 drivers it touched, I decided to
revert the entire patch. Continuing to constantify the other three could
too easily lead to introduction of future bugs.
Fixes: d86e64768859 ("rtlwifi: rtl818x: constify local structures")
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Cc: Stable <stable@vger.kernel.org>
Cc: Julia Lawall <Julia.Lawall@lip6.fr>
---
Kalle,
My apologies for letting these bugs to get by my review and testing. As
they affect kernel 4.8, please push this patch as soon as possible.
Thanks,
Larry
---
drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c | 2 +-
drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c | 2 +-
8 files changed, 8 insertions(+), 8 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
index e7b11b4..47e32cb 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8188ee/sw.c
@@ -280,7 +280,7 @@ static struct rtl_mod_params rtl88ee_mod_params = {
.debug = DBG_EMERG,
};
-static const struct rtl_hal_cfg rtl88ee_hal_cfg = {
+static struct rtl_hal_cfg rtl88ee_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl88e_pci",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
index 5c46a98..5400a96 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ce/sw.c
@@ -254,7 +254,7 @@ static struct rtl_mod_params rtl92ce_mod_params = {
.debug = DBG_EMERG,
};
-static const struct rtl_hal_cfg rtl92ce_hal_cfg = {
+static struct rtl_hal_cfg rtl92ce_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl92c_pci",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
index a9c39eb..60f42ae 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192de/sw.c
@@ -258,7 +258,7 @@ static struct rtl_mod_params rtl92de_mod_params = {
.debug = DBG_EMERG,
};
-static const struct rtl_hal_cfg rtl92de_hal_cfg = {
+static struct rtl_hal_cfg rtl92de_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl8192de",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
index ac299cb..c31c6bf 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192ee/sw.c
@@ -262,7 +262,7 @@ static struct rtl_mod_params rtl92ee_mod_params = {
.debug = DBG_EMERG,
};
-static const struct rtl_hal_cfg rtl92ee_hal_cfg = {
+static struct rtl_hal_cfg rtl92ee_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl92ee_pci",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index a652d45..9378b0d 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -302,7 +302,7 @@ static struct rtl_mod_params rtl92se_mod_params = {
/* Because memory R/W bursting will cause system hang/crash
* for 92se, so we don't read back after every write action */
-static const struct rtl_hal_cfg rtl92se_hal_cfg = {
+static struct rtl_hal_cfg rtl92se_hal_cfg = {
.bar_id = 1,
.write_readback = false,
.name = "rtl92s_pci",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
index 89c828a..ff49a8c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723ae/sw.c
@@ -276,7 +276,7 @@ static struct rtl_mod_params rtl8723e_mod_params = {
.disable_watchdog = false,
};
-static const struct rtl_hal_cfg rtl8723e_hal_cfg = {
+static struct rtl_hal_cfg rtl8723e_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl8723e_pci",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
index 20b53f0..2101793 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8723be/sw.c
@@ -276,7 +276,7 @@ static struct rtl_mod_params rtl8723be_mod_params = {
.ant_sel = 0,
};
-static const struct rtl_hal_cfg rtl8723be_hal_cfg = {
+static struct rtl_hal_cfg rtl8723be_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl8723be_pci",
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index 22f687b1..4159f9b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -316,7 +316,7 @@ static struct rtl_mod_params rtl8821ae_mod_params = {
.disable_watchdog = 0,
};
-static const struct rtl_hal_cfg rtl8821ae_hal_cfg = {
+static struct rtl_hal_cfg rtl8821ae_hal_cfg = {
.bar_id = 2,
.write_readback = true,
.name = "rtl8821ae_pci",
--
2.10.0
^ permalink raw reply related
* [mac80211] BUG_ON with current -git (4.8.0-11417-g24532f7)
From: Sergey Senozhatsky @ 2016-10-10 15:03 UTC (permalink / raw)
To: David S. Miller
Cc: Johannes Berg, linux-wireless, netdev, linux-kernel,
Sergey Senozhatsky, Sergey Senozhatsky, linux-next,
Stephen Rothwell
Hello,
current -git kills my system. adding
if (!virt_addr_valid(&aad[2])) {
WARN_ON(1);
return -EINVAL;
}
to ieee80211_aes_ccm_decrypt() given the following backtrace
WARNING: CPU: 5 PID: 252 at net/mac80211/aes_ccm.c:77 ieee80211_aes_ccm_decrypt+0xc8/0x197
CPU: 5 PID: 252 Comm: irq/29-iwlwifi Tainted: G W 4.8.0-next-20161010-dbg-00007-g79797e9-dirty #88
ffffc90000413638 ffffffff811ff0e3 0000000000000000 0000000000000000
ffffc90000413678 ffffffff8103fe91 0000004d000001c8 1ffff920000826d3
ffff88040fc526d8 0000000000000008 ffffc90000413978 ffffc9000041397a
Call Trace:
[<ffffffff811ff0e3>] dump_stack+0x4f/0x65
[<ffffffff8103fe91>] __warn+0xc2/0xdd
[<ffffffff8103ff1c>] warn_slowpath_null+0x1d/0x1f
[<ffffffff8142aaa5>] ieee80211_aes_ccm_decrypt+0xc8/0x197
[<ffffffff810ed595>] ? __put_page+0x3c/0x3f
[<ffffffff8131fa42>] ? put_page+0x4a/0x62
[<ffffffff813218d3>] ? __pskb_pull_tail+0x1e8/0x279
[<ffffffff8141a7dc>] ? ccmp_special_blocks.isra.5+0x51/0x12d
[<ffffffff8141b226>] ieee80211_crypto_ccmp_decrypt+0x1ba/0x221
[<ffffffff81432e80>] ieee80211_rx_handlers+0x52a/0x19c2
[<ffffffff81070000>] ? start_dl_timer+0xa8/0xb4
[<ffffffff8107462d>] ? put_lock_stats.isra.24+0xe/0x20
[<ffffffff8108ebec>] ? del_timer+0x57/0x61
[<ffffffff814351a8>] ieee80211_prepare_and_rx_handle+0xcd6/0xd2a
[<ffffffff810742a5>] ? local_clock+0x10/0x12
[<ffffffff8107642b>] ? __lock_acquire.isra.31+0x202/0x57e
[<ffffffff8143207b>] ? rcu_read_unlock+0x23/0x23
[<ffffffff81066e77>] ? sched_clock_cpu+0x17/0xc6
[<ffffffff814357ab>] ieee80211_rx_napi+0x5af/0x698
[<ffffffff810742c0>] ? get_lock_stats+0x19/0x50
[<ffffffff8107462d>] ? put_lock_stats.isra.24+0xe/0x20
[<ffffffffa023aaa9>] iwl_mvm_rx_rx_mpdu+0x5ab/0x60c [iwlmvm]
[<ffffffff810742c0>] ? get_lock_stats+0x19/0x50
[<ffffffffa0235c80>] iwl_mvm_rx+0x45/0x69 [iwlmvm]
[<ffffffffa01a989e>] iwl_pcie_rx_handle+0x478/0x584 [iwlwifi]
[<ffffffffa01aaafd>] iwl_pcie_irq_handler+0x39c/0x52d [iwlwifi]
[<ffffffff81080824>] ? irq_finalize_oneshot+0xa7/0xa7
[<ffffffff81080841>] irq_thread_fn+0x1d/0x34
[<ffffffff81080ab5>] irq_thread+0xe6/0x1bb
[<ffffffff8108093a>] ? wake_threads_waitq+0x2c/0x2c
[<ffffffff810809cf>] ? irq_thread_dtor+0x95/0x95
[<ffffffff81059d79>] kthread+0xc6/0xce
[<ffffffff8107462d>] ? put_lock_stats.isra.24+0xe/0x20
[<ffffffff81059cb3>] ? __list_del_entry+0x22/0x22
[<ffffffff814669d2>] ret_from_fork+0x22/0x30
---[ end trace 94da6d4698b938b2 ]---
-ss
^ permalink raw reply
* Re: [PATCH v2] ath10k: cache calibration data when the core is stopped
From: Marty Faltesek @ 2016-10-10 15:01 UTC (permalink / raw)
To: Valo, Kalle; +Cc: ath10k@lists.infradead.org, linux-wireless@vger.kernel.org
In-Reply-To: <8760p0jlv4.fsf@kamboji.qca.qualcomm.com>
ath10k: cache calibration data when the core is stopped
Caching calibration data allows it to be accessed when the
device is not active.
Signed-off-by: Marty Faltesek <mfaltesek@google.com>
On Mon, Oct 10, 2016 at 10:54 AM, Valo, Kalle <kvalo@qca.qualcomm.com> wrote:
> Marty Faltesek <mfaltesek@google.com> writes:
>
>> Caching calibration data allows it to be accessed when the
>> device is not active.
>>
>> ---
>
> Signed-off-by missing. Can you send it as a reply to this message and
> I'll add it to v3?
>
>> drivers/net/wireless/ath/ath10k/core.h | 1 +
>> drivers/net/wireless/ath/ath10k/debug.c | 72 ++++++++++++++-------------------
>> 2 files changed, 31 insertions(+), 42 deletions(-)
>>
>> diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
>> index 6e5aa2d..7274ebe 100644
>> --- a/drivers/net/wireless/ath/ath10k/core.h
>> +++ b/drivers/net/wireless/ath/ath10k/core.h
>> @@ -452,6 +452,7 @@ struct ath10k_debug {
>> u32 nf_cal_period;
>>
>> struct ath10k_fw_crash_data *fw_crash_data;
>> + void *cal_data;
>
> To properly document locking I'll move this under the "protected by
> conf_mutex" comment.
>
>> -static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file)
>> +static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
>> {
>> - struct ath10k *ar = inode->i_private;
>> - void *buf;
>> u32 hi_addr;
>> __le32 addr;
>> int ret;
>>
>> - mutex_lock(&ar->conf_mutex);
>
> I'll add lockdep_assert_held() here.
>
>> static ssize_t ath10k_debug_cal_data_read(struct file *file,
>> - char __user *user_buf,
>> - size_t count, loff_t *ppos)
>> + char __user *user_buf,
>> + size_t count, loff_t *ppos)
>> {
>> struct ath10k *ar = file->private_data;
>> - void *buf = file->private_data;
>>
>> return simple_read_from_buffer(user_buf, count, ppos,
>> - buf, ar->hw_params.cal_data_len);
>> -}
>
> I'll add locking to this function.
>
>> @@ -2343,7 +2327,9 @@ int ath10k_debug_create(struct ath10k *ar)
>> ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data));
>> if (!ar->debug.fw_crash_data)
>> return -ENOMEM;
>> -
>> + ar->debug.cal_data = vzalloc(ar->hw_params.cal_data_len);
>> + if (!ar->debug.cal_data)
>> + return -ENOMEM;
>> INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
>> INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
>> INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
>> @@ -2355,7 +2341,9 @@ int ath10k_debug_create(struct ath10k *ar)
>> void ath10k_debug_destroy(struct ath10k *ar)
>> {
>> vfree(ar->debug.fw_crash_data);
>> + vfree(ar->debug.cal_data);
>> ar->debug.fw_crash_data = NULL;
>> + ar->debug.cal_data = NULL;
>
> Actually I gave you a bad advice, this won't work as
> ar->hw_params.cal_data_len is not yet initialised, we initialise it only
> after we have probed the capabilities during the first firmware boot. I
> changed the allocation to a fixed length buffer for now, it's only few
> kBs virtual memory anyway so it shouldn't matter to anyone.
>
> I have now v3 ready and tested. I'll just need your Signed-off-by and I
> can then submit it.
>
> --
> Kalle Valo
^ permalink raw reply
* Re: [PATCH v2] ath10k: cache calibration data when the core is stopped
From: Valo, Kalle @ 2016-10-10 14:54 UTC (permalink / raw)
To: Marty Faltesek; +Cc: ath10k@lists.infradead.org, linux-wireless@vger.kernel.org
In-Reply-To: <1475699037-136212-1-git-send-email-mfaltesek@google.com>
Marty Faltesek <mfaltesek@google.com> writes:
> Caching calibration data allows it to be accessed when the
> device is not active.
>
> ---
Signed-off-by missing. Can you send it as a reply to this message and
I'll add it to v3?
> drivers/net/wireless/ath/ath10k/core.h | 1 +
> drivers/net/wireless/ath/ath10k/debug.c | 72 ++++++++++++++-------------=
------
> 2 files changed, 31 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireles=
s/ath/ath10k/core.h
> index 6e5aa2d..7274ebe 100644
> --- a/drivers/net/wireless/ath/ath10k/core.h
> +++ b/drivers/net/wireless/ath/ath10k/core.h
> @@ -452,6 +452,7 @@ struct ath10k_debug {
> u32 nf_cal_period;
> =20
> struct ath10k_fw_crash_data *fw_crash_data;
> + void *cal_data;
To properly document locking I'll move this under the "protected by
conf_mutex" comment.
> -static int ath10k_debug_cal_data_open(struct inode *inode, struct file *=
file)
> +static int ath10k_debug_cal_data_fetch(struct ath10k *ar)
> {
> - struct ath10k *ar =3D inode->i_private;
> - void *buf;
> u32 hi_addr;
> __le32 addr;
> int ret;
> =20
> - mutex_lock(&ar->conf_mutex);
I'll add lockdep_assert_held() here.
> static ssize_t ath10k_debug_cal_data_read(struct file *file,
> - char __user *user_buf,
> - size_t count, loff_t *ppos)
> + char __user *user_buf,
> + size_t count, loff_t *ppos)
> {
> struct ath10k *ar =3D file->private_data;
> - void *buf =3D file->private_data;
> =20
> return simple_read_from_buffer(user_buf, count, ppos,
> - buf, ar->hw_params.cal_data_len);
> -}
I'll add locking to this function.
> @@ -2343,7 +2327,9 @@ int ath10k_debug_create(struct ath10k *ar)
> ar->debug.fw_crash_data =3D vzalloc(sizeof(*ar->debug.fw_crash_data));
> if (!ar->debug.fw_crash_data)
> return -ENOMEM;
> -
> + ar->debug.cal_data =3D vzalloc(ar->hw_params.cal_data_len);
> + if (!ar->debug.cal_data)
> + return -ENOMEM;
> INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs);
> INIT_LIST_HEAD(&ar->debug.fw_stats.vdevs);
> INIT_LIST_HEAD(&ar->debug.fw_stats.peers);
> @@ -2355,7 +2341,9 @@ int ath10k_debug_create(struct ath10k *ar)
> void ath10k_debug_destroy(struct ath10k *ar)
> {
> vfree(ar->debug.fw_crash_data);
> + vfree(ar->debug.cal_data);
> ar->debug.fw_crash_data =3D NULL;
> + ar->debug.cal_data =3D NULL;
Actually I gave you a bad advice, this won't work as
ar->hw_params.cal_data_len is not yet initialised, we initialise it only
after we have probed the capabilities during the first firmware boot. I
changed the allocation to a fixed length buffer for now, it's only few
kBs virtual memory anyway so it shouldn't matter to anyone.
I have now v3 ready and tested. I'll just need your Signed-off-by and I
can then submit it.
--=20
Kalle Valo=
^ permalink raw reply
* [PATCH] ath10k: Fix kernel panic due to race in accessing arvif list
From: Vasanthakumar Thiagarajan @ 2016-10-10 14:21 UTC (permalink / raw)
To: ath10k; +Cc: linux-wireless, Vasanthakumar Thiagarajan
arvifs list is traversed within data_lock spin_lock in tasklet
context to fill channel information from the corresponding vif.
This means any access to arvifs list for add/del operations
should also be protected with the same spin_lock to avoid the
race. Fix this by performing list add/del on arvfis within the
data_lock. This could fix kernel panic something like the below.
LR is at ath10k_htt_rx_pktlog_completion_handler+0x100/0xb6c [ath10k_core]
PC is at ath10k_htt_rx_pktlog_completion_handler+0x1c0/0xb6c [ath10k_core]
Internal error: Oops: 17 [#1] PREEMPT SMP ARM
[<bf4857f4>] (ath10k_htt_rx_pktlog_completion_handler+0x2f4/0xb6c [ath10k_core])
[<bf487540>] (ath10k_htt_txrx_compl_task+0x8b4/0x1188 [ath10k_core])
[<c00312d4>] (tasklet_action+0x8c/0xec)
[<c00309a8>] (__do_softirq+0xdc/0x208)
[<c0030d6c>] (irq_exit+0x84/0xe0)
[<c005db04>] (__handle_domain_irq+0x80/0xa0)
[<c00085c4>] (gic_handle_irq+0x38/0x5c)
[<c0009640>] (__irq_svc+0x40/0x74)
(gdb) list *(ath10k_htt_rx_pktlog_completion_handler+0x1c0)
0x136c0 is in ath10k_htt_rx_h_channel (drivers/net/wireless/ath/ath10k/htt_rx.c:769)
764 struct cfg80211_chan_def def;
765
766 lockdep_assert_held(&ar->data_lock);
767
768 list_for_each_entry(arvif, &ar->arvifs, list) {
769 if (arvif->vdev_id == vdev_id &&
770 ath10k_mac_vif_chan(arvif->vif, &def) == 0)
771 return def.chan;
772 }
773
Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qti.qualcomm.com>
---
drivers/net/wireless/ath/ath10k/mac.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 2e5d2ca..691b7b5 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -4931,7 +4931,9 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
}
ar->free_vdev_map &= ~(1LL << arvif->vdev_id);
+ spin_lock_bh(&ar->data_lock);
list_add(&arvif->list, &ar->arvifs);
+ spin_unlock_bh(&ar->data_lock);
/* It makes no sense to have firmware do keepalives. mac80211 already
* takes care of this with idle connection polling.
@@ -5082,7 +5084,9 @@ err_peer_delete:
err_vdev_delete:
ath10k_wmi_vdev_delete(ar, arvif->vdev_id);
ar->free_vdev_map |= 1LL << arvif->vdev_id;
+ spin_lock_bh(&ar->data_lock);
list_del(&arvif->list);
+ spin_unlock_bh(&ar->data_lock);
err:
if (arvif->beacon_buf) {
@@ -5128,7 +5132,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
arvif->vdev_id, ret);
ar->free_vdev_map |= 1LL << arvif->vdev_id;
+ spin_lock_bh(&ar->data_lock);
list_del(&arvif->list);
+ spin_unlock_bh(&ar->data_lock);
if (arvif->vdev_type == WMI_VDEV_TYPE_AP ||
arvif->vdev_type == WMI_VDEV_TYPE_IBSS) {
--
1.9.1
^ permalink raw reply related
* Re: [PATCH] iwlwifi: pcie: reduce "unsupported splx" to a warning
From: Luca Coelho @ 2016-10-10 14:02 UTC (permalink / raw)
To: Chris Rorvick, Intel Linux Wireless, Emmanuel Grumbach,
Johannes Berg, Kalle Valo, Oren Givon
Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20161010071943.4717-1-chris@rorvick.com>
Hi,
On Mon, 2016-10-10 at 02:19 -0500, Chris Rorvick wrote:
> Commit bcb079a14d75 ("iwlwifi: pcie: retrieve and parse ACPI power
> limitations") looks for a specific structure in the ACPI tables for
> setting the default power limit. The data returned for at least some
> dual band chipsets is not recognized, though. For example, the AC 8260
> reports the following:
This is not coming from the NIC itself, but from the platform's ACPI
tables. Can you tell us which platform you are using?
> Name (SPLX, Package (0x04)
> {
> Zero,
> Package (0x03)
> {
> 0,
> 1200,
> 1000
> },
> Package (0x03)
> {
> 0,
> 1200,
> 1000
> },
> Package (0x03)
> {
> 0,
> 1200,
> 1000
> }
> })
This is not the structure that we are expecting. We expect this:
Name (SPLX, Package (0x02)
{
Zero,
Package (0x03)
{
0x07,
<value>,
<value>
}
})
...as you correctly pointed out. The data in the structure you have is
not for WiFi (actually I don't think 0 is a valid value, but I'll
double-check).
> The current logic expects exactly two elements in the outer package,
> causing the above to be ignored and the power limit unset.
>
> Despite the interface being fully functional after initialization, the
> above condition is reported as an error. Knock the message down to a
> warning and provide better context for understanding its consequence.
Reducing this to a warning is an easy way to reduce the verbosity of
the problem, but I think the correct thing to do would be to accept
multiple entries and ignore the ones that don't have the WIFI marker.
And only type-check the WIFI ones.
There are other things that look a bit inconsistent in this code...
I'll try to find the official ACPI table definitions for this entries
to make sure it's correct.
> Signed-off-by: Chris Rorvick <chris@rorvick.com>
> ---
> drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
> index 78cf9a7..19b531f 100644
> --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
> +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
> @@ -540,7 +540,7 @@ static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
> splx->package.count != 2 ||
> splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
> splx->package.elements[0].integer.value != 0) {
> - IWL_ERR(trans, "Unsupported splx structure\n");
> + IWL_WARN(trans, "Unsupported splx structure, not limiting WiFi power\n");
> return 0;
> }
If this is really bothering you, I guess I could apply this patch for
now. But as I said, this is not solving the actual problem.
--
Cheers,
Luca.
^ permalink raw reply
* [PATCH] cfg80211: Check radar_detect and num_different_channels with beacon interface combinations.
From: Purushottam Kushwaha @ 2016-10-10 12:07 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, jouni, usdutt, amarnath, pkushwah
This commit enhances the current beacon interval validation to also consider
the "radar_detect" and "num_different_channels".
Rename "cfg80211_validate_beacon_int" to "cfg80211_validate_beacon_combination"
as the validation considers other parameters.
Signed-off-by: Purushottam Kushwaha <pkushwah@qti.qualcomm.com>
---
net/wireless/core.h | 7 +++++--
net/wireless/mesh.c | 7 +++++++
net/wireless/nl80211.c | 32 ++++++++++++++------------------
net/wireless/util.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++---
4 files changed, 72 insertions(+), 23 deletions(-)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 21e3188..e39c8a9 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -474,8 +474,11 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
const u8 *rates, unsigned int n_rates,
u32 *mask);
-int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- enum nl80211_iftype iftype, u32 beacon_int);
+int
+cfg80211_validate_beacon_combination(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype,
+ struct cfg80211_chan_def *chandef,
+ u32 beacon_int);
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, int num);
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index fa2066b..1d864b4 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -178,6 +178,13 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
NL80211_IFTYPE_MESH_POINT))
return -EINVAL;
+ err = cfg80211_validate_beacon_combination(rdev,
+ NL80211_IFTYPE_MESH_POINT,
+ &setup->chandef,
+ setup->beacon_interval);
+ if (err)
+ return err;
+
err = rdev_join_mesh(rdev, dev, conf, setup);
if (!err) {
memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 903cd5a..eb2bfae 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3807,11 +3807,6 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.dtim_period =
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
- err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
- params.beacon_interval);
- if (err)
- return err;
-
/*
* In theory, some of these attributes should be required here
* but since they were not used when the command was originally
@@ -3899,6 +3894,13 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
wdev->iftype))
return -EINVAL;
+ err = cfg80211_validate_beacon_combination(rdev,
+ dev->ieee80211_ptr->iftype,
+ ¶ms.chandef,
+ params.beacon_interval);
+ if (err)
+ return err;
+
if (info->attrs[NL80211_ATTR_TX_RATES]) {
err = nl80211_parse_tx_bitrate_mask(info, ¶ms.beacon_rate);
if (err)
@@ -8157,11 +8159,6 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
ibss.beacon_interval =
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
- err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
- ibss.beacon_interval);
- if (err)
- return err;
-
if (!rdev->ops->join_ibss)
return -EOPNOTSUPP;
@@ -8188,6 +8185,12 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
if (err)
return err;
+ err = cfg80211_validate_beacon_combination(rdev, NL80211_IFTYPE_ADHOC,
+ &ibss.chandef,
+ ibss.beacon_interval);
+ if (err)
+ return err;
+
if (!cfg80211_reg_can_beacon(&rdev->wiphy, &ibss.chandef,
NL80211_IFTYPE_ADHOC))
return -EINVAL;
@@ -9419,17 +9422,10 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
nla_get_u32(info->attrs[NL80211_ATTR_MCAST_RATE])))
return -EINVAL;
- if (info->attrs[NL80211_ATTR_BEACON_INTERVAL]) {
+ if (info->attrs[NL80211_ATTR_BEACON_INTERVAL])
setup.beacon_interval =
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
- err = cfg80211_validate_beacon_int(rdev,
- NL80211_IFTYPE_MESH_POINT,
- setup.beacon_interval);
- if (err)
- return err;
- }
-
if (info->attrs[NL80211_ATTR_DTIM_PERIOD]) {
setup.dtim_period =
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
diff --git a/net/wireless/util.c b/net/wireless/util.c
index fe39ece..c5cf3b7 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1558,24 +1558,67 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
}
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
-int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- enum nl80211_iftype iftype, u32 beacon_int)
+int
+cfg80211_validate_beacon_combination(struct cfg80211_registered_device *rdev,
+ enum nl80211_iftype iftype,
+ struct cfg80211_chan_def *chandef,
+ u32 beacon_int)
{
struct wireless_dev *wdev;
- int res = 0;
+ int res = 0, i;
u32 bi_prev, tmp_bi;
struct iface_combination_params params;
+ struct ieee80211_channel *ch;
+ enum cfg80211_chan_mode chmode;
+ struct ieee80211_channel
+ *used_channels[CFG80211_MAX_NUM_DIFFERENT_CHANNELS];
if (beacon_int < 10 || beacon_int > 10000)
return -EINVAL;
memset(¶ms, 0, sizeof(params));
+ memset(used_channels, 0, sizeof(used_channels));
+ used_channels[0] = chandef->chan;
+ params.num_different_channels = 1;
params.iftype_num[iftype] = 1;
+ res = cfg80211_chandef_dfs_required(&rdev->wiphy, chandef, iftype);
+ if (res < 0)
+ return res;
+ if (res)
+ params.radar_detect = BIT(chandef->width);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->beacon_interval)
continue;
+ mutex_lock_nested(&wdev->mtx, 1);
+ __acquire(wdev->mtx);
+ cfg80211_get_chan_state(wdev, &ch, &chmode,
+ ¶ms.radar_detect);
+ wdev_unlock(wdev);
+
+ switch (chmode) {
+ case CHAN_MODE_UNDEFINED:
+ break;
+ case CHAN_MODE_SHARED:
+ for (i = 0; i < CFG80211_MAX_NUM_DIFFERENT_CHANNELS; i++)
+ if (!used_channels[i] || used_channels[i] == ch)
+ break;
+
+ if (i == CFG80211_MAX_NUM_DIFFERENT_CHANNELS)
+ return -EBUSY;
+
+ if (!used_channels[i]) {
+ used_channels[i] = ch;
+ params.num_different_channels++;
+ }
+ break;
+ case CHAN_MODE_EXCLUSIVE:
+ params.num_different_channels++;
+ break;
+ }
+
params.iftype_num[wdev->iftype]++;
}
--
1.9.1
^ permalink raw reply related
* [PATCH] cfg80211: Create structure for combination check/iter function parameters
From: Purushottam Kushwaha @ 2016-10-10 12:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, jouni, usdutt, amarnath, pkushwah
Move growing parameter list to a structure for check/iter combination
functions in cfg80211 and mac80211.
Signed-off-by: Purushottam Kushwaha <pkushwah@qti.qualcomm.com>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 25 ++++-----
include/net/cfg80211.h | 56 ++++++++++----------
net/mac80211/util.c | 42 ++++++++-------
net/wireless/util.c | 59 +++++++++-------------
4 files changed, 86 insertions(+), 96 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 1e73c88..00c5fb2 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -414,24 +414,25 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
struct brcmf_cfg80211_vif *vif,
enum nl80211_iftype new_type)
{
- int iftype_num[NUM_NL80211_IFTYPES];
+ struct iface_combination_params params;
struct brcmf_cfg80211_vif *pos;
bool check_combos = false;
int ret = 0;
- memset(&iftype_num[0], 0, sizeof(iftype_num));
+ memset(¶ms, 0, sizeof(params));
+ params.num_different_channels = 1;
+
list_for_each_entry(pos, &cfg->vif_list, list)
if (pos == vif) {
- iftype_num[new_type]++;
+ params.iftype_num[new_type]++;
} else {
/* concurrent interfaces so need check combinations */
check_combos = true;
- iftype_num[pos->wdev.iftype]++;
+ params.iftype_num[pos->wdev.iftype]++;
}
if (check_combos)
- ret = cfg80211_check_combinations(cfg->wiphy, 1, 0,
- iftype_num, 0, false);
+ ret = cfg80211_check_combinations(cfg->wiphy, ¶ms);
return ret;
}
@@ -439,16 +440,16 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
enum nl80211_iftype new_type)
{
- int iftype_num[NUM_NL80211_IFTYPES];
+ struct iface_combination_params params;
struct brcmf_cfg80211_vif *pos;
- memset(&iftype_num[0], 0, sizeof(iftype_num));
+ memset(¶ms, 0, sizeof(params));
list_for_each_entry(pos, &cfg->vif_list, list)
- iftype_num[pos->wdev.iftype]++;
+ params.iftype_num[pos->wdev.iftype]++;
- iftype_num[new_type]++;
- return cfg80211_check_combinations(cfg->wiphy, 1, 0,
- iftype_num, 0, false);
+ params.iftype_num[new_type]++;
+ params.num_different_channels = 1;
+ return cfg80211_check_combinations(cfg->wiphy, ¶ms);
}
static void convert_key_from_CPU(struct brcmf_wsec_key *key,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 49aa6a0..4e509ed 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -772,6 +772,30 @@ struct cfg80211_csa_settings {
};
/**
+ * struct iface_combination_params - input parameters for interface combinations
+ *
+ * Used to pass interface combination parameters
+ *
+ * @num_different_channels: the number of different channels we want
+ * to use for verification
+ * @radar_detect: a bitmap where each bit corresponds to a channel
+ * width where radar detection is needed, as in the definition of
+ * &struct ieee80211_iface_combination.@radar_detect_widths
+ * @iftype_num: array with the numbers of interfaces of each interface
+ * type. The index is the interface type as specified in &enum
+ * nl80211_iftype.
+ * @beacon_gcd: a value specifying GCD of all beaconing interfaces.
+ * @diff_bi: a flag which denotes beacon intervals are different or same.
+ */
+struct iface_combination_params {
+ int num_different_channels;
+ u8 radar_detect;
+ int iftype_num[NUM_NL80211_IFTYPES];
+ u32 beacon_gcd;
+ bool diff_bi;
+};
+
+/**
* enum station_parameters_apply_mask - station parameter values to apply
* @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp)
* @STATION_PARAM_APPLY_CAPABILITY: apply new capability
@@ -5583,41 +5607,20 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
* cfg80211_check_combinations - check interface combinations
*
* @wiphy: the wiphy
- * @num_different_channels: the number of different channels we want
- * to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
- * width where radar detection is needed, as in the definition of
- * &struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the numbers of interfaces of each interface
- * type. The index is the interface type as specified in &enum
- * nl80211_iftype.
- * @beacon_gcd: a value specifying GCD of all beaconing interfaces.
- * @diff_bi: a flag which denotes beacon intervals are different or same.
+ * @params: the interface combinations parameter.
*
* This function can be called by the driver to check whether a
* combination of interfaces and their types are allowed according to
* the interface combinations.
*/
int cfg80211_check_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
- const u32 beacon_gcd, bool diff_bi);
+ struct iface_combination_params *params);
/**
* cfg80211_iter_combinations - iterate over matching combinations
*
* @wiphy: the wiphy
- * @num_different_channels: the number of different channels we want
- * to use for verification
- * @radar_detect: a bitmap where each bit corresponds to a channel
- * width where radar detection is needed, as in the definition of
- * &struct ieee80211_iface_combination.@radar_detect_widths
- * @iftype_num: array with the numbers of interfaces of each interface
- * type. The index is the interface type as specified in &enum
- * nl80211_iftype.
- * @beacon_gcd: a value specifying GCD of all beaconing interfaces.
- * @diff_bi: a flag which denotes beacon intervals are different or same.
+ * @params: the interface combinations parameter.
* @iter: function to call for each matching combination
* @data: pointer to pass to iter function
*
@@ -5626,10 +5629,7 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
* purposes.
*/
int cfg80211_iter_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
- const u32 beacon_gcd, bool diff_bi,
+ struct iface_combination_params *params,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index cfef5ce..0607fe1 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3308,9 +3308,8 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
struct ieee80211_sub_if_data *sdata_iter;
enum nl80211_iftype iftype = sdata->wdev.iftype;
- int num[NUM_NL80211_IFTYPES];
+ struct iface_combination_params params;
struct ieee80211_chanctx *ctx;
- int num_different_channels = 0;
int total = 1;
lockdep_assert_held(&local->chanctx_mtx);
@@ -3322,9 +3321,6 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
!chandef->chan))
return -EINVAL;
- if (chandef)
- num_different_channels = 1;
-
if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
return -EINVAL;
@@ -3335,24 +3331,27 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
return 0;
}
- memset(num, 0, sizeof(num));
+ memset(¶ms, 0, sizeof(params));
+
+ if (chandef)
+ params.num_different_channels = 1;
if (iftype != NL80211_IFTYPE_UNSPECIFIED)
- num[iftype] = 1;
+ params.iftype_num[iftype] = 1;
list_for_each_entry(ctx, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
continue;
radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
- num_different_channels++;
+ params.num_different_channels++;
continue;
}
if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
cfg80211_chandef_compatible(chandef,
&ctx->conf.def))
continue;
- num_different_channels++;
+ params.num_different_channels++;
}
list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
@@ -3365,16 +3364,16 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
continue;
- num[wdev_iter->iftype]++;
+ params.iftype_num[wdev_iter->iftype]++;
total++;
}
if (total == 1 && !radar_detect)
return 0;
- return cfg80211_check_combinations(local->hw.wiphy,
- num_different_channels,
- radar_detect, num, 0, false);
+ params.radar_detect = radar_detect;
+
+ return cfg80211_check_combinations(local->hw.wiphy, ¶ms);
}
static void
@@ -3390,30 +3389,29 @@ ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
int ieee80211_max_num_channels(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
- int num[NUM_NL80211_IFTYPES] = {};
struct ieee80211_chanctx *ctx;
- int num_different_channels = 0;
- u8 radar_detect = 0;
+ struct iface_combination_params params;
u32 max_num_different_channels = 1;
int err;
lockdep_assert_held(&local->chanctx_mtx);
+ memset(¶ms, 0, sizeof(params));
list_for_each_entry(ctx, &local->chanctx_list, list) {
if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
continue;
- num_different_channels++;
+ params.num_different_channels++;
- radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
+ params.radar_detect |=
+ ieee80211_chanctx_radar_detect(local, ctx);
}
list_for_each_entry_rcu(sdata, &local->interfaces, list)
- num[sdata->wdev.iftype]++;
+ params.iftype_num[sdata->wdev.iftype]++;
- err = cfg80211_iter_combinations(local->hw.wiphy,
- num_different_channels, radar_detect,
- num, 0, false, ieee80211_iter_max_chans,
+ err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms,
+ ieee80211_iter_max_chans,
&max_num_different_channels);
if (err < 0)
return err;
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 0d3bda4..fe39ece 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1562,52 +1562,47 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, u32 beacon_int)
{
struct wireless_dev *wdev;
- bool diff_bi = false;
int res = 0;
- u32 bi_prev, tmp_bi, gcd;
- int iftype_num[NUM_NL80211_IFTYPES];
+ u32 bi_prev, tmp_bi;
+ struct iface_combination_params params;
if (beacon_int < 10 || beacon_int > 10000)
return -EINVAL;
- memset(iftype_num, 0, sizeof(iftype_num));
- iftype_num[iftype] = 1;
+ memset(¶ms, 0, sizeof(params));
+ params.iftype_num[iftype] = 1;
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->beacon_interval)
continue;
- iftype_num[wdev->iftype]++;
+ params.iftype_num[wdev->iftype]++;
}
/* GCD(n) = n */
- gcd = beacon_int;
+ params.beacon_gcd = beacon_int;
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->beacon_interval)
continue;
if (wdev->beacon_interval != beacon_int) {
- diff_bi = true;
+ params.diff_bi = true;
/* Get the GCD */
bi_prev = wdev->beacon_interval;
while (bi_prev != 0) {
tmp_bi = bi_prev;
- bi_prev = gcd % bi_prev;
- gcd = tmp_bi;
+ bi_prev = params.beacon_gcd % bi_prev;
+ params.beacon_gcd = tmp_bi;
}
break;
}
}
- res = cfg80211_check_combinations(&rdev->wiphy, 0, 0,
- iftype_num, gcd, diff_bi);
+ res = cfg80211_check_combinations(&rdev->wiphy, ¶ms);
return (res < 0) ? res : 0;
}
int cfg80211_iter_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
- const u32 beacon_gcd, bool diff_bi,
+ struct iface_combination_params *params,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data)
@@ -1618,7 +1613,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
int num_interfaces = 0;
u32 used_iftypes = 0;
- if (radar_detect) {
+ if (params->radar_detect) {
rcu_read_lock();
regdom = rcu_dereference(cfg80211_regdomain);
if (regdom)
@@ -1627,8 +1622,8 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
}
for (iftype = 0; iftype < NUM_NL80211_IFTYPES; iftype++) {
- num_interfaces += iftype_num[iftype];
- if (iftype_num[iftype] > 0 &&
+ num_interfaces += params->iftype_num[iftype];
+ if (params->iftype_num[iftype] > 0 &&
!(wiphy->software_iftypes & BIT(iftype)))
used_iftypes |= BIT(iftype);
}
@@ -1642,7 +1637,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if (num_interfaces > c->max_interfaces)
continue;
- if (num_different_channels > c->num_different_channels)
+ if (params->num_different_channels > c->num_different_channels)
continue;
limits = kmemdup(c->limits, sizeof(limits[0]) * c->n_limits,
@@ -1657,16 +1652,17 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
all_iftypes |= limits[j].types;
if (!(limits[j].types & BIT(iftype)))
continue;
- if (limits[j].max < iftype_num[iftype])
+ if (limits[j].max < params->iftype_num[iftype])
goto cont;
- limits[j].max -= iftype_num[iftype];
+ limits[j].max -= params->iftype_num[iftype];
}
}
- if (radar_detect != (c->radar_detect_widths & radar_detect))
+ if (params->radar_detect !=
+ (c->radar_detect_widths & params->radar_detect))
goto cont;
- if (radar_detect && c->radar_detect_regions &&
+ if (params->radar_detect && c->radar_detect_regions &&
!(c->radar_detect_regions & BIT(region)))
goto cont;
@@ -1678,11 +1674,11 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;
- if (beacon_gcd) {
+ if (params->beacon_gcd) {
if (c->beacon_int_min_gcd &&
- beacon_gcd < c->beacon_int_min_gcd)
+ params->beacon_gcd < c->beacon_int_min_gcd)
return -EINVAL;
- if (!c->beacon_int_min_gcd && diff_bi)
+ if (!c->beacon_int_min_gcd && params->diff_bi)
goto cont;
}
@@ -1708,16 +1704,11 @@ cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
}
int cfg80211_check_combinations(struct wiphy *wiphy,
- const int num_different_channels,
- const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES],
- const u32 beacon_gcd, bool diff_bi)
+ struct iface_combination_params *params)
{
int err, num = 0;
- err = cfg80211_iter_combinations(wiphy, num_different_channels,
- radar_detect, iftype_num,
- beacon_gcd, diff_bi,
+ err = cfg80211_iter_combinations(wiphy, params,
cfg80211_iter_sum_ifcombs, &num);
if (err)
return err;
--
1.9.1
^ permalink raw reply related
* [PATCH v9] cfg80211: Provision to allow the support for different beacon intervals
From: Purushottam Kushwaha @ 2016-10-10 12:06 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, jouni, usdutt, amarnath, pkushwah
This commit provides a mechanism for the host drivers to advertise the
support for different beacon intervals among the respective interface
combinations in a group, through beacon_int_min_gcd (u32).
This beacon_int_min_gcd will be compared against GCD of all beaconing
interfaces of matching combinations.
Following sets the expectation for beacon_int_min_gcd.
= 0 - all beacon intervals for different interfaces must be same.
> 0 - any beacon interval for the interface part of this combination AND
*GCD* of all beacon intervals from beaconing interfaces of this
combination must be greator or equal to this value.
Signed-off-by: Purushottam Kushwaha <pkushwah@qti.qualcomm.com>
---
.../broadcom/brcm80211/brcmfmac/cfg80211.c | 6 ++-
include/net/cfg80211.h | 18 ++++++++-
include/uapi/linux/nl80211.h | 8 +++-
net/mac80211/util.c | 4 +-
net/wireless/core.h | 2 +-
net/wireless/nl80211.c | 14 +++++--
net/wireless/util.c | 43 ++++++++++++++++++++--
7 files changed, 79 insertions(+), 16 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index b777e1b..1e73c88 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -430,7 +430,8 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg,
}
if (check_combos)
- ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+ ret = cfg80211_check_combinations(cfg->wiphy, 1, 0,
+ iftype_num, 0, false);
return ret;
}
@@ -446,7 +447,8 @@ static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg,
iftype_num[pos->wdev.iftype]++;
iftype_num[new_type]++;
- return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num);
+ return cfg80211_check_combinations(cfg->wiphy, 1, 0,
+ iftype_num, 0, false);
}
static void convert_key_from_CPU(struct brcmf_wsec_key *key,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index fe78f02..49aa6a0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -3080,6 +3080,12 @@ struct ieee80211_iface_limit {
* only in special cases.
* @radar_detect_widths: bitmap of channel widths supported for radar detection
* @radar_detect_regions: bitmap of regions supported for radar detection
+ * @beacon_int_min_gcd: This interface combination supports different
+ * beacon intervals.
+ * = 0 - all beacon intervals for different interface must be same.
+ * > 0 - any beacon interval for the interface part of this combination AND
+ * *GCD* of all beacon intervals from beaconing interfaces of this
+ * combination must be greator or equal to this value.
*
* With this structure the driver can describe which interface
* combinations it supports concurrently.
@@ -3100,7 +3106,7 @@ struct ieee80211_iface_limit {
* };
*
*
- * 2. Allow #{AP, P2P-GO} <= 8, channels = 1, 8 total:
+ * 2. Allow #{AP, P2P-GO} <= 8, BI min gcd = 10, channels = 1, 8 total:
*
* struct ieee80211_iface_limit limits2[] = {
* { .max = 8, .types = BIT(NL80211_IFTYPE_AP) |
@@ -3111,6 +3117,7 @@ struct ieee80211_iface_limit {
* .n_limits = ARRAY_SIZE(limits2),
* .max_interfaces = 8,
* .num_different_channels = 1,
+ * .beacon_int_min_gcd = 10,
* };
*
*
@@ -3138,6 +3145,7 @@ struct ieee80211_iface_combination {
bool beacon_int_infra_match;
u8 radar_detect_widths;
u8 radar_detect_regions;
+ u32 beacon_int_min_gcd;
};
struct ieee80211_txrx_stypes {
@@ -5583,6 +5591,8 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
* @iftype_num: array with the numbers of interfaces of each interface
* type. The index is the interface type as specified in &enum
* nl80211_iftype.
+ * @beacon_gcd: a value specifying GCD of all beaconing interfaces.
+ * @diff_bi: a flag which denotes beacon intervals are different or same.
*
* This function can be called by the driver to check whether a
* combination of interfaces and their types are allowed according to
@@ -5591,7 +5601,8 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy);
int cfg80211_check_combinations(struct wiphy *wiphy,
const int num_different_channels,
const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES]);
+ const int iftype_num[NUM_NL80211_IFTYPES],
+ const u32 beacon_gcd, bool diff_bi);
/**
* cfg80211_iter_combinations - iterate over matching combinations
@@ -5605,6 +5616,8 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
* @iftype_num: array with the numbers of interfaces of each interface
* type. The index is the interface type as specified in &enum
* nl80211_iftype.
+ * @beacon_gcd: a value specifying GCD of all beaconing interfaces.
+ * @diff_bi: a flag which denotes beacon intervals are different or same.
* @iter: function to call for each matching combination
* @data: pointer to pass to iter function
*
@@ -5616,6 +5629,7 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
const int num_different_channels,
const u8 radar_detect,
const int iftype_num[NUM_NL80211_IFTYPES],
+ const u32 beacon_gcd, bool diff_bi,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data);
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 56368e9..3c19cca 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -4280,6 +4280,9 @@ enum nl80211_iface_limit_attrs {
* of supported channel widths for radar detection.
* @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
* of supported regulatory regions for radar detection.
+ * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of
+ * different beacon intervals supported by all the interface combinations
+ * in this group (if not present, all beacon interval must match).
* @NUM_NL80211_IFACE_COMB: number of attributes
* @MAX_NL80211_IFACE_COMB: highest attribute number
*
@@ -4287,8 +4290,8 @@ enum nl80211_iface_limit_attrs {
* limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
* => allows an AP and a STA that must match BIs
*
- * numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
- * => allows 8 of AP/GO
+ * numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8,
+ * => allows 8 of AP/GO that can have BI gcd >= min gcd
*
* numbers = [ #{STA} <= 2 ], channels = 2, max = 2
* => allows two STAs on different channels
@@ -4314,6 +4317,7 @@ enum nl80211_if_combination_attrs {
NL80211_IFACE_COMB_NUM_CHANNELS,
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
+ NL80211_IFACE_COMB_BI_MIN_GCD,
/* keep last */
NUM_NL80211_IFACE_COMB,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 545c79a..cfef5ce 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -3374,7 +3374,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
return cfg80211_check_combinations(local->hw.wiphy,
num_different_channels,
- radar_detect, num);
+ radar_detect, num, 0, false);
}
static void
@@ -3413,7 +3413,7 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
err = cfg80211_iter_combinations(local->hw.wiphy,
num_different_channels, radar_detect,
- num, ieee80211_iter_max_chans,
+ num, 0, false, ieee80211_iter_max_chans,
&max_num_different_channels);
if (err < 0)
return err;
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 08d2e94..21e3188 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -475,7 +475,7 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
u32 *mask);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int);
+ enum nl80211_iftype iftype, u32 beacon_int);
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
enum nl80211_iftype iftype, int num);
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index c510810..903cd5a 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1075,6 +1075,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
c->radar_detect_regions)))
goto nla_put_failure;
+ if (c->beacon_int_min_gcd &&
+ nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
+ c->beacon_int_min_gcd))
+ goto nla_put_failure;
nla_nest_end(msg, nl_combi);
}
@@ -3803,7 +3807,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.dtim_period =
nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);
- err = cfg80211_validate_beacon_int(rdev, params.beacon_interval);
+ err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
+ params.beacon_interval);
if (err)
return err;
@@ -8152,7 +8157,8 @@ static int nl80211_join_ibss(struct sk_buff *skb, struct genl_info *info)
ibss.beacon_interval =
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
- err = cfg80211_validate_beacon_int(rdev, ibss.beacon_interval);
+ err = cfg80211_validate_beacon_int(rdev, NL80211_IFTYPE_ADHOC,
+ ibss.beacon_interval);
if (err)
return err;
@@ -9417,7 +9423,9 @@ static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
setup.beacon_interval =
nla_get_u32(info->attrs[NL80211_ATTR_BEACON_INTERVAL]);
- err = cfg80211_validate_beacon_int(rdev, setup.beacon_interval);
+ err = cfg80211_validate_beacon_int(rdev,
+ NL80211_IFTYPE_MESH_POINT,
+ setup.beacon_interval);
if (err)
return err;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 8edce22..0d3bda4 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1559,30 +1559,55 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
- u32 beacon_int)
+ enum nl80211_iftype iftype, u32 beacon_int)
{
struct wireless_dev *wdev;
+ bool diff_bi = false;
int res = 0;
+ u32 bi_prev, tmp_bi, gcd;
+ int iftype_num[NUM_NL80211_IFTYPES];
if (beacon_int < 10 || beacon_int > 10000)
return -EINVAL;
+ memset(iftype_num, 0, sizeof(iftype_num));
+ iftype_num[iftype] = 1;
+
+ list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
+ if (!wdev->beacon_interval)
+ continue;
+
+ iftype_num[wdev->iftype]++;
+ }
+
+ /* GCD(n) = n */
+ gcd = beacon_int;
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->beacon_interval)
continue;
if (wdev->beacon_interval != beacon_int) {
- res = -EINVAL;
+ diff_bi = true;
+ /* Get the GCD */
+ bi_prev = wdev->beacon_interval;
+ while (bi_prev != 0) {
+ tmp_bi = bi_prev;
+ bi_prev = gcd % bi_prev;
+ gcd = tmp_bi;
+ }
break;
}
}
- return res;
+ res = cfg80211_check_combinations(&rdev->wiphy, 0, 0,
+ iftype_num, gcd, diff_bi);
+ return (res < 0) ? res : 0;
}
int cfg80211_iter_combinations(struct wiphy *wiphy,
const int num_different_channels,
const u8 radar_detect,
const int iftype_num[NUM_NL80211_IFTYPES],
+ const u32 beacon_gcd, bool diff_bi,
void (*iter)(const struct ieee80211_iface_combination *c,
void *data),
void *data)
@@ -1653,6 +1678,14 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
if ((all_iftypes & used_iftypes) != used_iftypes)
goto cont;
+ if (beacon_gcd) {
+ if (c->beacon_int_min_gcd &&
+ beacon_gcd < c->beacon_int_min_gcd)
+ return -EINVAL;
+ if (!c->beacon_int_min_gcd && diff_bi)
+ goto cont;
+ }
+
/* This combination covered all interface types and
* supported the requested numbers, so we're good.
*/
@@ -1677,12 +1710,14 @@ cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
int cfg80211_check_combinations(struct wiphy *wiphy,
const int num_different_channels,
const u8 radar_detect,
- const int iftype_num[NUM_NL80211_IFTYPES])
+ const int iftype_num[NUM_NL80211_IFTYPES],
+ const u32 beacon_gcd, bool diff_bi)
{
int err, num = 0;
err = cfg80211_iter_combinations(wiphy, num_different_channels,
radar_detect, iftype_num,
+ beacon_gcd, diff_bi,
cfg80211_iter_sum_ifcombs, &num);
if (err)
return err;
--
1.9.1
^ permalink raw reply related
* Re: [PATCH v5 3/4] cfg80211: configure multicast to unicast for AP interfaces
From: Johannes Berg @ 2016-10-10 10:28 UTC (permalink / raw)
To: Michael Braun; +Cc: linux-wireless, projekt-wlan, netdev
In-Reply-To: <1475865574-5384-3-git-send-email-michael-dev@fami-braun.de>
> *
> + * @NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED: Multicast packets
> should be
> + * send out as unicast to all stations.
You should document what type of attribute is expected. You probably
wanted a flag attribute, but ...
> + [NL80211_ATTR_MULTICAST_TO_UNICAST_ENABLED] = { .type =
> NLA_U8, },
have u8 in the policy, yet
> + enabled = nla_get_flag(nla);
actually use as a flag :)
In addition to that, I think you should clarify the "per-BSS" comment
in nl80211, and also clarify (at the same place) what kind of
functionality is expected from this.
johannes
^ permalink raw reply
* Re: [PATCH] mac80211: enable to inject a-msdu frames using monitor interface
From: Johannes Berg @ 2016-10-10 10:16 UTC (permalink / raw)
To: Michael Braun; +Cc: linux-wireless, projekt-wlan
In-Reply-To: <1475872162-2835-1-git-send-email-michael-dev@fami-braun.de>
On Fri, 2016-10-07 at 22:29 +0200, Michael Braun wrote:
>
> I guess the same is needed for packets with IEEE80211_TX_CTRL_AMSDU
> set.
I don't think that's true, since we don't get here after A-MSDU
building in mac80211.
> /* preserve EOSP bit */
> ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
>
> + /* preserve A-MSDU bit for MONITOR interfaces to allow
> injecting
> + * A-MSDU frames
> + */
> + if (info->flags & IEEE80211_TX_CTL_INJECTED ||
> + info->control.flags & IEEE80211_TX_CTRL_AMSDU)
> + ack_policy |= *p & IEEE80211_QOS_CTL_A_MSDU_PRESENT;
However, why not just unconditionally preserve it?
johannes
^ permalink raw reply
* Re: [RFC] mac80211: fix A-MSDU outer SA/DA
From: Johannes Berg @ 2016-10-10 10:13 UTC (permalink / raw)
To: Michael Braun; +Cc: linux-wireless, projekt-wlan
In-Reply-To: <1475874542-9014-1-git-send-email-michael-dev@fami-braun.de>
>
> + /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer
> SA/DA
> + * fields needs to be changed to BSSID for A-MSDU frames
> depending
> + * on FromDS/ToDS values.
> + */
> + hdr = data;
> + if (bssid && (hdr->frame_control &
> cpu_to_le16(IEEE80211_FCTL_FROMDS)))
> + memcpy(amsdu_hdr.h_source, bssid, ETH_ALEN);
> + if (bssid && (hdr->frame_control &
> cpu_to_le16(IEEE80211_FCTL_TODS)))
> + memcpy(amsdu_hdr.h_dest, bssid, ETH_ALEN);
>
You should probably use ieee80211_has_tods() and ieee80211_has_fromds()
johannes
^ permalink raw reply
* [PATCH] mac80211_hwsim: make multi-channel ops const
From: Johannes Berg @ 2016-10-10 10:09 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
Instead of building the multi-channel ops at runtime, declare
the common ops with a macro and build both that way, so that
the multi-channel ops can also be const.
As a side effect, due to the removed code, this decreases the
size of the module (while shifting data from .bss to .text
due to the newly added const).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
drivers/net/wireless/mac80211_hwsim.c | 79 ++++++++++++++++++-----------------
1 file changed, 40 insertions(+), 39 deletions(-)
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 431f13b4faf6..f9ba0772e471 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -2256,35 +2256,51 @@ static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw,
WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN);
}
+#define HWSIM_COMMON_OPS \
+ .tx = mac80211_hwsim_tx, \
+ .start = mac80211_hwsim_start, \
+ .stop = mac80211_hwsim_stop, \
+ .add_interface = mac80211_hwsim_add_interface, \
+ .change_interface = mac80211_hwsim_change_interface, \
+ .remove_interface = mac80211_hwsim_remove_interface, \
+ .config = mac80211_hwsim_config, \
+ .configure_filter = mac80211_hwsim_configure_filter, \
+ .bss_info_changed = mac80211_hwsim_bss_info_changed, \
+ .sta_add = mac80211_hwsim_sta_add, \
+ .sta_remove = mac80211_hwsim_sta_remove, \
+ .sta_notify = mac80211_hwsim_sta_notify, \
+ .set_tim = mac80211_hwsim_set_tim, \
+ .conf_tx = mac80211_hwsim_conf_tx, \
+ .get_survey = mac80211_hwsim_get_survey, \
+ CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) \
+ .ampdu_action = mac80211_hwsim_ampdu_action, \
+ .flush = mac80211_hwsim_flush, \
+ .get_tsf = mac80211_hwsim_get_tsf, \
+ .set_tsf = mac80211_hwsim_set_tsf, \
+ .get_et_sset_count = mac80211_hwsim_get_et_sset_count, \
+ .get_et_stats = mac80211_hwsim_get_et_stats, \
+ .get_et_strings = mac80211_hwsim_get_et_strings,
+
static const struct ieee80211_ops mac80211_hwsim_ops = {
- .tx = mac80211_hwsim_tx,
- .start = mac80211_hwsim_start,
- .stop = mac80211_hwsim_stop,
- .add_interface = mac80211_hwsim_add_interface,
- .change_interface = mac80211_hwsim_change_interface,
- .remove_interface = mac80211_hwsim_remove_interface,
- .config = mac80211_hwsim_config,
- .configure_filter = mac80211_hwsim_configure_filter,
- .bss_info_changed = mac80211_hwsim_bss_info_changed,
- .sta_add = mac80211_hwsim_sta_add,
- .sta_remove = mac80211_hwsim_sta_remove,
- .sta_notify = mac80211_hwsim_sta_notify,
- .set_tim = mac80211_hwsim_set_tim,
- .conf_tx = mac80211_hwsim_conf_tx,
- .get_survey = mac80211_hwsim_get_survey,
- CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
- .ampdu_action = mac80211_hwsim_ampdu_action,
+ HWSIM_COMMON_OPS
.sw_scan_start = mac80211_hwsim_sw_scan,
.sw_scan_complete = mac80211_hwsim_sw_scan_complete,
- .flush = mac80211_hwsim_flush,
- .get_tsf = mac80211_hwsim_get_tsf,
- .set_tsf = mac80211_hwsim_set_tsf,
- .get_et_sset_count = mac80211_hwsim_get_et_sset_count,
- .get_et_stats = mac80211_hwsim_get_et_stats,
- .get_et_strings = mac80211_hwsim_get_et_strings,
};
-static struct ieee80211_ops mac80211_hwsim_mchan_ops;
+static const struct ieee80211_ops mac80211_hwsim_mchan_ops = {
+ HWSIM_COMMON_OPS
+ .hw_scan = mac80211_hwsim_hw_scan,
+ .cancel_hw_scan = mac80211_hwsim_cancel_hw_scan,
+ .sw_scan_start = NULL,
+ .sw_scan_complete = NULL,
+ .remain_on_channel = mac80211_hwsim_roc,
+ .cancel_remain_on_channel = mac80211_hwsim_croc,
+ .add_chanctx = mac80211_hwsim_add_chanctx,
+ .remove_chanctx = mac80211_hwsim_remove_chanctx,
+ .change_chanctx = mac80211_hwsim_change_chanctx,
+ .assign_vif_chanctx = mac80211_hwsim_assign_vif_chanctx,
+ .unassign_vif_chanctx = mac80211_hwsim_unassign_vif_chanctx,
+};
struct hwsim_new_radio_params {
unsigned int channels;
@@ -3360,21 +3376,6 @@ static int __init init_mac80211_hwsim(void)
if (channels < 1)
return -EINVAL;
- mac80211_hwsim_mchan_ops = mac80211_hwsim_ops;
- mac80211_hwsim_mchan_ops.hw_scan = mac80211_hwsim_hw_scan;
- mac80211_hwsim_mchan_ops.cancel_hw_scan = mac80211_hwsim_cancel_hw_scan;
- mac80211_hwsim_mchan_ops.sw_scan_start = NULL;
- mac80211_hwsim_mchan_ops.sw_scan_complete = NULL;
- mac80211_hwsim_mchan_ops.remain_on_channel = mac80211_hwsim_roc;
- mac80211_hwsim_mchan_ops.cancel_remain_on_channel = mac80211_hwsim_croc;
- mac80211_hwsim_mchan_ops.add_chanctx = mac80211_hwsim_add_chanctx;
- mac80211_hwsim_mchan_ops.remove_chanctx = mac80211_hwsim_remove_chanctx;
- mac80211_hwsim_mchan_ops.change_chanctx = mac80211_hwsim_change_chanctx;
- mac80211_hwsim_mchan_ops.assign_vif_chanctx =
- mac80211_hwsim_assign_vif_chanctx;
- mac80211_hwsim_mchan_ops.unassign_vif_chanctx =
- mac80211_hwsim_unassign_vif_chanctx;
-
spin_lock_init(&hwsim_radio_lock);
err = register_pernet_device(&hwsim_net_ops);
--
2.8.1
^ permalink raw reply related
* Re: [PATCH] Report scan_abort as part of iw phy
From: Johannes Berg @ 2016-10-10 9:21 UTC (permalink / raw)
To: Ola Olsson; +Cc: linux-wireless, Ola Olsson
In-Reply-To: <1475934036-5981-1-git-send-email-ola1olsson@gmail.com>
On Sat, 2016-10-08 at 15:40 +0200, Ola Olsson wrote:
> nl80211: abort_scan has not been reported under the 'Supported
> commands'
> category when calling iw phy. Add that.
>
> Signed-off-by: Ola Olsson <ola.olsson@sonymobile.com>
> ---
> net/wireless/nl80211.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
> index 95d55d2..0bbce4f 100644
> --- a/net/wireless/nl80211.c
> +++ b/net/wireless/nl80211.c
> @@ -1526,6 +1526,7 @@ static int nl80211_send_wiphy(struct
> cfg80211_registered_device *rdev,
> CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
> CMD(mgmt_tx, FRAME);
> CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
> + CMD(abort_scan, ABORT_SCAN);
>
You can't add this here, it has to be inside the "state->split" if.
johannes
^ permalink raw reply
* Re: [PATCH] Report scan_abort as part of iw phy
From: Kalle Valo @ 2016-10-10 9:13 UTC (permalink / raw)
To: Ola Olsson; +Cc: johannes, linux-wireless, Ola Olsson
In-Reply-To: <1475934036-5981-1-git-send-email-ola1olsson@gmail.com>
Ola Olsson <ola1olsson@gmail.com> writes:
> nl80211: abort_scan has not been reported under the 'Supported commands'
> category when calling iw phy. Add that.
>
> Signed-off-by: Ola Olsson <ola.olsson@sonymobile.com>
> ---
> net/wireless/nl80211.c | 1 +
> 1 file changed, 1 insertion(+)
You should prefix the title with "cfg80211: " (or "nl80211: ", not
really sure which one is more suitable).
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches#subject_name
--
Kalle Valo
^ permalink raw reply
* [PATCH] iwlwifi: pcie: reduce "unsupported splx" to a warning
From: Chris Rorvick @ 2016-10-10 7:19 UTC (permalink / raw)
To: Intel Linux Wireless, Luca Coelho, Emmanuel Grumbach,
Johannes Berg, Kalle Valo, Oren Givon
Cc: linux-wireless, netdev, linux-kernel, Chris Rorvick
Commit bcb079a14d75 ("iwlwifi: pcie: retrieve and parse ACPI power
limitations") looks for a specific structure in the ACPI tables for
setting the default power limit. The data returned for at least some
dual band chipsets is not recognized, though. For example, the AC 8260
reports the following:
Name (SPLX, Package (0x04)
{
Zero,
Package (0x03)
{
0,
1200,
1000
},
Package (0x03)
{
0,
1200,
1000
},
Package (0x03)
{
0,
1200,
1000
}
})
The current logic expects exactly two elements in the outer package,
causing the above to be ignored and the power limit unset.
Despite the interface being fully functional after initialization, the
above condition is reported as an error. Knock the message down to a
warning and provide better context for understanding its consequence.
Signed-off-by: Chris Rorvick <chris@rorvick.com>
---
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 78cf9a7..19b531f 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -540,7 +540,7 @@ static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
splx->package.count != 2 ||
splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
splx->package.elements[0].integer.value != 0) {
- IWL_ERR(trans, "Unsupported splx structure\n");
+ IWL_WARN(trans, "Unsupported splx structure, not limiting WiFi power\n");
return 0;
}
--
2.10.1
^ permalink raw reply related
* Re: [PATCH v7 1/3] Documentation: dt: net: add ath9k wireless device binding
From: Martin Blumenstingl @ 2016-10-09 9:54 UTC (permalink / raw)
To: Rob Herring
Cc: ath9k-devel, devicetree, linux-wireless, ath9k-devel, mcgrof,
mark.rutland, kvalo, chunkeey, arend.vanspriel, julian.calaby,
bjorn, linux, nbd
In-Reply-To: <20161009012856.GK18158@rob-hp-laptop>
On Sun, Oct 9, 2016 at 3:28 AM, Rob Herring <robh@kernel.org> wrote:
> On Sun, Oct 02, 2016 at 11:47:41PM +0200, Martin Blumenstingl wrote:
>> Add documentation how devicetree can be used to configure ath9k based
>> devices.
>>
>> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
>> ---
>> .../devicetree/bindings/net/wireless/qca,ath9k.txt | 30 ++++++++++++++++++++++
>> 1 file changed, 30 insertions(+)
>> create mode 100644 Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
>>
>> diff --git a/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
>> new file mode 100644
>> index 0000000..9b58ede
>> --- /dev/null
>> +++ b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
>> @@ -0,0 +1,30 @@
>> +* Qualcomm Atheros ath9k wireless devices
>> +
>> +This node provides properties for configuring the ath9k wireless device. The
>> +node is expected to be specified as a child node of the PCI controller to
>> +which the wireless chip is connected.
>> +
>> +Required properties:
>> +- compatible: For PCI and PCIe devices this should be an identifier following
>> + the format as defined in "PCI Bus Binding to Open Firmware"
>> + Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
>> + where VVVV is the PCI vendor ID and DDDD is PCI device ID.
>
> Are there some known values you can document here? Like the one in the
> example.
what do you have in mind there?
there are lots of supported device IDs just with vendor 0x168c (Atheros):
echo $(grep 'PCI_VDEVICE(ATHEROS'
drivers/net/wireless/ath/ath9k/pci.c; grep '{
PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS'
drivers/net/wireless/ath/ath9k/pci.c -A1) | grep -Eo "0x[
0-9A-Z]{4}" | sort -u
Also some device IDs seem to be used by different chips, for example
0x0029 is used for both, AR9220 and AR9223 - see [0]
I could extend the documentation with something like:
vendor ID is usually 168c (Atheros) and device ID is one of the
following, depending on the actual chipset:
- 002d: AR9227 (PCI variant of AR9287)
- 002e: AR9287 (PCI-e)
- ...
>> +- reg: Address and length of the register set for the device.
>> +
>> +Optional properties:
>> +- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
>> + ath9k wireless chip (in this case the calibration /
>> + EEPROM data will be loaded from userspace using the
>> + kernel firmware loader).
>> +- mac-address: See ethernet.txt in the parent directory
>> +- local-mac-address: See ethernet.txt in the parent directory
>> +
>> +
>> +In this example, the node is defined as child node of the PCI controller:
>> +&pci0 {
>> + ath9k@168c,002d {
>
> wifi@...
will fix that, thanks for the hint
[0] https://wireless.wiki.kernel.org/en/users/drivers/ath9k/devices
^ permalink raw reply
* Re: [PATCH v7 1/3] Documentation: dt: net: add ath9k wireless device binding
From: Rob Herring @ 2016-10-09 1:28 UTC (permalink / raw)
To: Martin Blumenstingl
Cc: ath9k-devel, devicetree, linux-wireless, ath9k-devel, mcgrof,
mark.rutland, kvalo, chunkeey, arend.vanspriel, julian.calaby,
bjorn, linux, nbd
In-Reply-To: <20161002214743.2263-2-martin.blumenstingl@googlemail.com>
On Sun, Oct 02, 2016 at 11:47:41PM +0200, Martin Blumenstingl wrote:
> Add documentation how devicetree can be used to configure ath9k based
> devices.
>
> Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
> ---
> .../devicetree/bindings/net/wireless/qca,ath9k.txt | 30 ++++++++++++++++++++++
> 1 file changed, 30 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
>
> diff --git a/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
> new file mode 100644
> index 0000000..9b58ede
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/net/wireless/qca,ath9k.txt
> @@ -0,0 +1,30 @@
> +* Qualcomm Atheros ath9k wireless devices
> +
> +This node provides properties for configuring the ath9k wireless device. The
> +node is expected to be specified as a child node of the PCI controller to
> +which the wireless chip is connected.
> +
> +Required properties:
> +- compatible: For PCI and PCIe devices this should be an identifier following
> + the format as defined in "PCI Bus Binding to Open Firmware"
> + Revision 2.1. One of the possible formats is "pciVVVV,DDDD"
> + where VVVV is the PCI vendor ID and DDDD is PCI device ID.
Are there some known values you can document here? Like the one in the
example.
> +- reg: Address and length of the register set for the device.
> +
> +Optional properties:
> +- qca,no-eeprom: Indicates that there is no physical EEPROM connected to the
> + ath9k wireless chip (in this case the calibration /
> + EEPROM data will be loaded from userspace using the
> + kernel firmware loader).
> +- mac-address: See ethernet.txt in the parent directory
> +- local-mac-address: See ethernet.txt in the parent directory
> +
> +
> +In this example, the node is defined as child node of the PCI controller:
> +&pci0 {
> + ath9k@168c,002d {
wifi@...
> + compatible = "pci168c,002d";
> + reg = <0x7000 0 0 0 0x1000>;
> + qca,no-eeprom;
> + };
> +};
> --
> 2.10.0
>
^ permalink raw reply
* Re: [PATCH 1/2] ath10k: add per peer htt tx stats support for 10.4
From: Yeoh Chun-Yeow @ 2016-10-08 14:16 UTC (permalink / raw)
To: akolli; +Cc: ath10k@lists.infradead.org, akolli,
linux-wireless@vger.kernel.org
In-Reply-To: <1475852332-18217-2-git-send-email-akolli@qti.qualcomm.com>
On Fri, Oct 7, 2016 at 10:58 PM, <akolli@qti.qualcomm.com> wrote:
> From: Anilkumar Kolli <akolli@qti.qualcomm.com>
>
> Per peer tx stats are part of 'HTT_10_4_T2H_MSG_TYPE_PEER_STATS'
> event, Firmware sends one HTT event for every four PPDUs.
> HTT payload has success pkts/bytes, failed pkts/bytes, retry
> pkts/bytes and rate info per ppdu.
> Peer stats are enabled through 'WMI_SERVICE_PEER_STATS',
> which are nowadays enabled by default.
>
> Parse peer stats and update the tx rate information per STA.
>
> tx rate, Peer stats are tested on QCA4019 with Firmware version
> 10.4-3.2.1-00028.
>
Is QCA988X supported? I have tried to test with
firmware-5.bin_10.2.4.70.56 but not working.
---
Chun-Yeow
^ permalink raw reply
* [PATCH] Report scan_abort as part of iw phy
From: Ola Olsson @ 2016-10-08 13:40 UTC (permalink / raw)
To: johannes; +Cc: linux-wireless, Ola Olsson, Ola Olsson
nl80211: abort_scan has not been reported under the 'Supported commands'
category when calling iw phy. Add that.
Signed-off-by: Ola Olsson <ola.olsson@sonymobile.com>
---
net/wireless/nl80211.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 95d55d2..0bbce4f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -1526,6 +1526,7 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *rdev,
CMD(set_bitrate_mask, SET_TX_BITRATE_MASK);
CMD(mgmt_tx, FRAME);
CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL);
+ CMD(abort_scan, ABORT_SCAN);
if (rdev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
i++;
if (nla_put_u32(msg, i, NL80211_CMD_SET_WIPHY_NETNS))
--
2.7.4
^ permalink raw reply related
* Re: [PATCHv4] mac80211: check A-MSDU inner frame source address on AP interfaces
From: michael-dev @ 2016-10-08 10:13 UTC (permalink / raw)
To: Johannes Berg
Cc: linux-wireless, projekt-wlan, kvalo, akarwar, nishants,
Larry.Finger, Jes.Sorensen
In-Reply-To: <1475753787.2015.13.camel@sipsolutions.net>
Am 06.10.2016 13:36, schrieb Johannes Berg:
> Could you test my patches in your scenario to see they do what we want?
> I'll resend as [PATCH] then, and think about applying them and perhaps
> backporting also.
I've tested them by running a new hostapd hwsim test [1] and after
applying [2].
I can confirm that this tests fails without your RFC series applied and
passes when your RFC series is applied.
So your RFC is fine.
Tested-by: Michael Braun <michael-dev@fami-braun.de>
Regards,
M. Braun
[1]
https://github.com/michael-dev/hostapd/commit/2caecdd9911529e39c6b8a83aac0cbe737dc8f65
[2] https://patchwork.kernel.org/patch/9367469/
^ permalink raw reply
* [RFC] mac80211: fix A-MSDU outer SA/DA
From: Michael Braun @ 2016-10-07 21:09 UTC (permalink / raw)
To: johannes; +Cc: Michael Braun, linux-wireless, projekt-wlan
According to IEEE 802.11-2012 section 8.3.2 table 8-19, the outer SA/DA
of A-MSDU frames need to be changed depending on FromDS/ToDS values.
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
---
net/mac80211/tx.c | 24 +++++++++++++++++++++++-
1 file changed, 23 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 5023966..87670b7 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -3050,7 +3050,7 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
int hdr_len = fast_tx->hdr_len - sizeof(rfc1042_header);
int subframe_len = skb->len - hdr_len;
void *data;
- u8 *qc;
+ u8 *qc, *bssid;
if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
return false;
@@ -3062,10 +3062,32 @@ static bool ieee80211_amsdu_prepare_head(struct ieee80211_sub_if_data *sdata,
&subframe_len))
return false;
+ switch (sdata->vif.type) {
+ case NL80211_IFTYPE_STATION:
+ bssid = sdata->u.mgd.bssid;
+ break;
+ case NL80211_IFTYPE_AP:
+ case NL80211_IFTYPE_AP_VLAN:
+ bssid = sdata->vif.addr;
+ break;
+ default:
+ bssid = NULL;
+ }
+
amsdu_hdr.h_proto = cpu_to_be16(subframe_len);
memcpy(amsdu_hdr.h_source, skb->data + fast_tx->sa_offs, ETH_ALEN);
memcpy(amsdu_hdr.h_dest, skb->data + fast_tx->da_offs, ETH_ALEN);
+ /* according to IEEE 802.11-2012 8.3.2 table 8-19, the outer SA/DA
+ * fields needs to be changed to BSSID for A-MSDU frames depending
+ * on FromDS/ToDS values.
+ */
+ hdr = data;
+ if (bssid && (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_FROMDS)))
+ memcpy(amsdu_hdr.h_source, bssid, ETH_ALEN);
+ if (bssid && (hdr->frame_control & cpu_to_le16(IEEE80211_FCTL_TODS)))
+ memcpy(amsdu_hdr.h_dest, bssid, ETH_ALEN);
+
data = skb_push(skb, sizeof(amsdu_hdr));
memmove(data, data + sizeof(amsdu_hdr), hdr_len);
memcpy(data + hdr_len, &amsdu_hdr, sizeof(amsdu_hdr));
--
2.1.4
^ permalink raw reply related
* [PATCH] mac80211: enable to inject a-msdu frames using monitor interface
From: Michael Braun @ 2016-10-07 20:29 UTC (permalink / raw)
To: johannes; +Cc: Michael Braun, linux-wireless, projekt-wlan
Problem: When injecting an A-MSDU using a PF_PACKET socket, the qos flag
IEEE80211_QOS_CTL_A_MSDU_PRESENT is cleared.
How to reproduce: Inject a frame on a mac80211 hwsim monitor interface and
have tshark sniffing on this monitor interface.
You'll see the packet twice: Once with correct flag and once with flag
cleared. On hwsim0, you'll only see the packet with a cleared flag.
I guess the same is needed for packets with IEEE80211_TX_CTRL_AMSDU set.
Signed-off-by: Michael Braun <michael-dev@fami-braun.de>
---
net/mac80211/wme.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/mac80211/wme.c b/net/mac80211/wme.c
index 9eb0aee..3faa972 100644
--- a/net/mac80211/wme.c
+++ b/net/mac80211/wme.c
@@ -248,6 +248,13 @@ void ieee80211_set_qos_hdr(struct ieee80211_sub_if_data *sdata,
/* preserve EOSP bit */
ack_policy = *p & IEEE80211_QOS_CTL_EOSP;
+ /* preserve A-MSDU bit for MONITOR interfaces to allow injecting
+ * A-MSDU frames
+ */
+ if (info->flags & IEEE80211_TX_CTL_INJECTED ||
+ info->control.flags & IEEE80211_TX_CTRL_AMSDU)
+ ack_policy |= *p & IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+
if (is_multicast_ether_addr(hdr->addr1) ||
sdata->noack_map & BIT(tid)) {
ack_policy |= IEEE80211_QOS_CTL_ACK_POLICY_NOACK;
--
2.1.4
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox