| From foo@baz Mon Apr 9 17:09:24 CEST 2018 |
| From: "Peter Große" <pegro@friiks.de> |
| Date: Wed, 13 Dec 2017 18:29:46 +0100 |
| Subject: mac80211: Fix setting TX power on monitor interfaces |
| |
| From: "Peter Große" <pegro@friiks.de> |
| |
| |
| [ Upstream commit 3a3713ec360138f806c6fc368d1de570f692b347 ] |
| |
| Instead of calling ieee80211_recalc_txpower on monitor interfaces |
| directly, call it using the virtual monitor interface, if one exists. |
| |
| In case of a single monitor interface given, reject setting TX power, |
| if no virtual monitor interface exists. |
| |
| That being checked, don't warn in ieee80211_bss_info_change_notify, |
| after setting TX power on a monitor interface. |
| |
| Fixes warning: |
| ------------[ cut here ]------------ |
| WARNING: CPU: 0 PID: 2193 at net/mac80211/driver-ops.h:167 |
| ieee80211_bss_info_change_notify+0x111/0x190 Modules linked in: uvcvideo |
| videobuf2_vmalloc videobuf2_memops videobuf2_v4l2 videobuf2_core |
| rndis_host cdc_ether usbnet mii tp_smapi(O) thinkpad_ec(O) ohci_hcd vboxpci(O) |
| vboxnetadp(O) vboxnetflt(O) v boxdrv(O) x86_pkg_temp_thermal kvm_intel kvm |
| irqbypass iwldvm iwlwifi ehci_pci ehci_hcd tpm_tis tpm_tis_core tpm CPU: 0 |
| PID: 2193 Comm: iw Tainted: G O 4.12.12-gentoo #2 task: |
| ffff880186fd5cc0 task.stack: ffffc90001b54000 RIP: |
| 0010:ieee80211_bss_info_change_notify+0x111/0x190 RSP: 0018:ffffc90001b57a10 |
| EFLAGS: 00010246 RAX: 0000000000000006 RBX: ffff8801052ce840 RCX: |
| 0000000000000064 RDX: 00000000fffffffc RSI: 0000000000040000 RDI: |
| ffff8801052ce840 RBP: ffffc90001b57a38 R08: 0000000000000062 R09: |
| 0000000000000000 R10: ffff8802144b5000 R11: ffff880049dc4614 R12: |
| 0000000000040000 R13: 0000000000000064 R14: ffff8802105f0760 R15: |
| ffffc90001b57b48 FS: 00007f92644b4580(0000) GS:ffff88021e200000(0000) |
| knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 |
| CR2: 00007f9263c109f0 CR3: 00000001df850000 CR4: 00000000000406f0 |
| Call Trace: |
| ieee80211_recalc_txpower+0x33/0x40 |
| ieee80211_set_tx_power+0x40/0x180 |
| nl80211_set_wiphy+0x32e/0x950 |
| |
| Reported-by: Peter GroÃe <pegro@friiks.de> |
| Signed-off-by: Peter GroÃe <pegro@friiks.de> |
| |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/mac80211/cfg.c | 28 +++++++++++++++++++++++++++- |
| net/mac80211/driver-ops.h | 3 ++- |
| 2 files changed, 29 insertions(+), 2 deletions(-) |
| |
| --- a/net/mac80211/cfg.c |
| +++ b/net/mac80211/cfg.c |
| @@ -2341,10 +2341,17 @@ static int ieee80211_set_tx_power(struct |
| struct ieee80211_sub_if_data *sdata; |
| enum nl80211_tx_power_setting txp_type = type; |
| bool update_txp_type = false; |
| + bool has_monitor = false; |
| |
| if (wdev) { |
| sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
| |
| + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
| + sdata = rtnl_dereference(local->monitor_sdata); |
| + if (!sdata) |
| + return -EOPNOTSUPP; |
| + } |
| + |
| switch (type) { |
| case NL80211_TX_POWER_AUTOMATIC: |
| sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL; |
| @@ -2383,15 +2390,34 @@ static int ieee80211_set_tx_power(struct |
| |
| mutex_lock(&local->iflist_mtx); |
| list_for_each_entry(sdata, &local->interfaces, list) { |
| + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) { |
| + has_monitor = true; |
| + continue; |
| + } |
| sdata->user_power_level = local->user_power_level; |
| if (txp_type != sdata->vif.bss_conf.txpower_type) |
| update_txp_type = true; |
| sdata->vif.bss_conf.txpower_type = txp_type; |
| } |
| - list_for_each_entry(sdata, &local->interfaces, list) |
| + list_for_each_entry(sdata, &local->interfaces, list) { |
| + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) |
| + continue; |
| ieee80211_recalc_txpower(sdata, update_txp_type); |
| + } |
| mutex_unlock(&local->iflist_mtx); |
| |
| + if (has_monitor) { |
| + sdata = rtnl_dereference(local->monitor_sdata); |
| + if (sdata) { |
| + sdata->user_power_level = local->user_power_level; |
| + if (txp_type != sdata->vif.bss_conf.txpower_type) |
| + update_txp_type = true; |
| + sdata->vif.bss_conf.txpower_type = txp_type; |
| + |
| + ieee80211_recalc_txpower(sdata, update_txp_type); |
| + } |
| + } |
| + |
| return 0; |
| } |
| |
| --- a/net/mac80211/driver-ops.h |
| +++ b/net/mac80211/driver-ops.h |
| @@ -164,7 +164,8 @@ static inline void drv_bss_info_changed( |
| if (WARN_ON_ONCE(sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE || |
| sdata->vif.type == NL80211_IFTYPE_NAN || |
| (sdata->vif.type == NL80211_IFTYPE_MONITOR && |
| - !sdata->vif.mu_mimo_owner))) |
| + !sdata->vif.mu_mimo_owner && |
| + !(changed & BSS_CHANGED_TXPOWER)))) |
| return; |
| |
| if (!check_sdata_in_driver(sdata)) |