* Re: mac80211: 3.9.0+: Invalid WDS/flush state and non-connecting station.
From: Ben Greear @ 2013-05-10 21:33 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <1368221128.8390.47.camel@jlt4.sipsolutions.net>
On 05/10/2013 02:25 PM, Johannes Berg wrote:
> On Fri, 2013-05-10 at 14:21 -0700, Ben Greear wrote:
>
>> void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
>> struct net_device *dev)
>> {
>> struct wireless_dev *wdev = dev->ieee80211_ptr;
>> struct cfg80211_deauth_request req;
>> u8 bssid[ETH_ALEN];
>>
>> ASSERT_WDEV_LOCK(wdev);
>>
>> printk("mlme_down: %s: type: %i sme_state: %i current-bss: %p\n",
>> dev->name, (int)(wdev->iftype), (int)(wdev->sme_state),
>> wdev->current_bss);
>>
>> I see this printout for the stuck station (this is dmesg | grep sta74,
>> so it skips errors about other interfaces that are also hung).
>>
>> I am guessing we should never be calling mlme_down with state
>> of CFG80211_SME_CONNECTED when bss is NULL?
>
> We should _never_ be in a state where current_bss is NULL but the state
> is != IDLE. The question I can't seem to find an answer for is how we
> got into that state, that we're in the state in down() is really less
> interesting.
>
> Since you seem to be able to reproduce this, maybe it'd help to mark all
> state transitions and current_bss assignments, and then backtrack them
> after the fact.
I'll work on instrumenting all of those assignments. I plan to use
a helper macro to assign them and print out call sites..
Thanks,
Ben
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* Re: mac80211: 3.9.0+: Invalid WDS/flush state and non-connecting station.
From: Johannes Berg @ 2013-05-10 21:25 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <518D64E6.8000102@candelatech.com>
On Fri, 2013-05-10 at 14:21 -0700, Ben Greear wrote:
> void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
> struct net_device *dev)
> {
> struct wireless_dev *wdev = dev->ieee80211_ptr;
> struct cfg80211_deauth_request req;
> u8 bssid[ETH_ALEN];
>
> ASSERT_WDEV_LOCK(wdev);
>
> printk("mlme_down: %s: type: %i sme_state: %i current-bss: %p\n",
> dev->name, (int)(wdev->iftype), (int)(wdev->sme_state),
> wdev->current_bss);
>
> I see this printout for the stuck station (this is dmesg | grep sta74,
> so it skips errors about other interfaces that are also hung).
>
> I am guessing we should never be calling mlme_down with state
> of CFG80211_SME_CONNECTED when bss is NULL?
We should _never_ be in a state where current_bss is NULL but the state
is != IDLE. The question I can't seem to find an answer for is how we
got into that state, that we're in the state in down() is really less
interesting.
Since you seem to be able to reproduce this, maybe it'd help to mark all
state transitions and current_bss assignments, and then backtrack them
after the fact.
johannes
^ permalink raw reply
* Re: mac80211: 3.9.0+: Invalid WDS/flush state and non-connecting station.
From: Ben Greear @ 2013-05-10 21:21 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless@vger.kernel.org
In-Reply-To: <518A9618.1020107@candelatech.com>
On 05/08/2013 11:14 AM, Ben Greear wrote:
> On 05/08/2013 10:58 AM, Johannes Berg wrote:
>> On Wed, 2013-05-08 at 09:18 -0700, Ben Greear wrote:
>>
>>> Ok, I reproduced this with yet more debugging printouts in the kernel.
>>>
>>> The symptom is this:
>>>
>>> The sme_state is SME_CONNECTED, so it bails out below before sending the
>>> 'connected' message to user-space.
>>
>> Is your system being really really really slow and/or are threads
>> getting pre-empted a lot? This maybe seem like a bit of a stretch, but
>> it seems possible that this happens:
>>
>> ieee80211_sta_rx_queued_mgmt() is running, possibly on one CPU, and is
>> somewhere between printing "associated" and calling
>> cfg80211_send_rx_assoc() (or in the call already, before taking the lock
>> though.)
>>
>> Then your interface is set down at the same time, possibly on a
>> different CPU. Here's where the scenario gets stretched, clearly your
>> interface is getting set down over a minute later, I don't see how you
>> could have stalled the other thread for that long.
>>
>> But if you did, then that thread is still processing things while the
>> interface is going down, cfg80211 didn't know anything about the
>> association having completed so it won't have disconnected, etc.
>>
>> So far, I haven't found any other scenario, nor a solution.
>
> It is not that slow or overloaded (at least most of the time,
> and in particular, I only had 20 virtual stations up on this system
> not doing much traffic...it easily handles 100's of stations).
>
> And, once it gets in this state..it stays there (overnight,
> with my app resetting the port (via 'ip link set down' and
> poking at wpa_supplicant) every minute or so in this case.
>
> I was wondering..in the cfg80211_mlme_down method (or perhaps
> some place similar), should we force sme state to IDLE
> with a big WARN_ON_ONCE or similar.
>
> That way, if it does get stuck somehow, we can recover by
> downing the interface and bringing it back up?
>
Here's some more debug info..hit it again today:
I added this debug code (on top of all my other patches and 3.9.1+).
void cfg80211_mlme_down(struct cfg80211_registered_device *rdev,
struct net_device *dev)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_deauth_request req;
u8 bssid[ETH_ALEN];
ASSERT_WDEV_LOCK(wdev);
printk("mlme_down: %s: type: %i sme_state: %i current-bss: %p\n",
dev->name, (int)(wdev->iftype), (int)(wdev->sme_state),
wdev->current_bss);
I see this printout for the stuck station (this is dmesg | grep sta74,
so it skips errors about other interfaces that are also hung).
I am guessing we should never be calling mlme_down with state
of CFG80211_SME_CONNECTED when bss is NULL?
I'm hoping I can get by with some sort of work-around patch
for the 3.9 kernel instead of trying to patch in your big
locking changes....
sta74: authenticate with 00:de:ad:1d:ea:00
sta74: send auth to 00:de:ad:1d:ea:00 (try 1/3)
sta74: authenticated
sta74: associate with 00:de:ad:1d:ea:00 (try 1/3)
sta74: RX AssocResp from 00:de:ad:1d:ea:00 (capab=0x1 status=0 aid=67)
IPv6: ADDRCONF(NETDEV_CHANGE): sta74: link becomes ready
sta74: associated
connect_result: sta74: type: 2 sme_state: 2
__cfg80211_disconnect: sta74: type: 2 sme_state: 2 conn-state: -1
mlme_down: sta74: type: 2 sme_state: 2 current-bss: (null)
mlme_down: sta74: type: 2 sme_state: 2 current-bss: (null)
sta74: Invalid WDS/flush state, type: 2 WDS: 5 flushed: 1
IPv6: ADDRCONF(NETDEV_UP): sta74: link is not ready
__cfg80211_disconnect: sta74: type: 2 sme_state: 2 conn-state: -1
mlme_down: sta74: type: 2 sme_state: 2 current-bss: (null)
mlme_down: sta74: type: 2 sme_state: 2 current-bss: (null)
IPv6: ADDRCONF(NETDEV_UP): sta74: link is not ready
sta74: authenticate with 00:de:ad:1d:ea:00
sta74: send auth to 00:de:ad:1d:ea:00 (try 1/3)
sta74: authenticated
sta74: associate with 00:de:ad:1d:ea:00 (try 1/3)
sta74: RX AssocResp from 00:de:ad:1d:ea:00 (capab=0x1 status=0 aid=67)
sta74: associated
connect_result: sta74: type: 2 sme_state: 2
IPv6: ADDRCONF(NETDEV_CHANGE): sta74: link becomes ready
> For what it's worth, I don't recall ever seeing this problem
> in 5.7, but it's way to rare to be able to bisect...
>
> Thanks,
> Ben
>
>>
>> johannes
>>
>
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH 3.10] cfg80211: fix wiphy_register error path
From: Johannes Berg @ 2013-05-10 18:41 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
If rfkill_register() fails in wiphy_register() the struct device
is unregistered but everything else isn't (regulatory, debugfs)
and we even leave the wiphy instance on all internal lists even
though it will likely be freed soon, which is clearly a problem.
Fix this by cleaning up properly.
Cc: stable@vger.kernel.org
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/core.c | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 68f0c96..c498c2b 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -639,17 +639,21 @@ int wiphy_register(struct wiphy *wiphy)
* cfg80211_mutex lock
*/
res = rfkill_register(rdev->rfkill);
- if (res)
- goto out_rm_dev;
+ if (res) {
+ device_del(&rdev->wiphy.dev);
+
+ mutex_lock(&cfg80211_mutex);
+ debugfs_remove_recursive(rdev->wiphy.debugfsdir);
+ list_del_rcu(&rdev->list);
+ wiphy_regulatory_deregister(wiphy);
+ mutex_unlock(&cfg80211_mutex);
+ return res;
+ }
rtnl_lock();
rdev->wiphy.registered = true;
rtnl_unlock();
return 0;
-
-out_rm_dev:
- device_del(&rdev->wiphy.dev);
- return res;
}
EXPORT_SYMBOL(wiphy_register);
--
1.8.0
^ permalink raw reply related
* Re: RTL driver for RTL8191SEvB and/or wpa-supplicant really broken at times
From: Matt Causey @ 2013-05-10 16:50 UTC (permalink / raw)
To: Norbert Preining; +Cc: linux-wireless, linux-kernel, hostap
In-Reply-To: <20130509115630.GC5111@gamma.logic.tuwien.ac.at>
Sorry - reply got bounced because I accidentially replied with HTML
mode enabled. Re-sending.
On Thu, May 9, 2013 at 7:56 AM, Norbert Preining <preining@logic.at> wrote:
>
> Dear all,
>
> here is a short status report on my experiences with:
> kernel 3.9.0
> wpa_supplicant 1.0
> hardware RTL191SEvB
> Debian/sid
>
> Short summary: broken to the degree that internet connection is impossible
>
> Sorry for the long mail, I tried to reduce to the essentials only.
>
> Contents:
> =========
> 0) hardware and software description
> 1) during connection permanent break off
> 2) connection seems established according to kernel and NM, but nothing
> works
> 3) if connection is working, ping times are crazy and connection breaks
> down suddenly
> 4) conclusion
>
>
> 0) hardware and software description
> ====================================
> Hardware:
> Lenovo Thinkpad Edge
> WLAN:
> 03:00.0 Network controller: Realtek Semiconductor Co., Ltd. RTL8191SEvB
> Wireless LAN Controller (rev 10)
> Subsystem: Realtek Semiconductor Co., Ltd. Device e020
> Flags: bus master, fast devsel, latency 0, IRQ 17
> I/O ports at 2000 [size=256]
> Memory at f0500000 (32-bit, non-prefetchable) [size=16K]
> Capabilities: [40] Power Management version 3
> Capabilities: [50] MSI: Enable- Count=1/1 Maskable- 64bit+
> Capabilities: [70] Express Legacy Endpoint, MSI 00
> Capabilities: [100] Advanced Error Reporting
> Capabilities: [140] Virtual Channel
> Capabilities: [160] Device Serial Number 88-55-22-fe-ff-4c-e0-00
> Kernel driver in use: rtl8192se
>
> Debian unstable up to date
> kernel 3.9.0
> # wpa_supplicant -v
> wpa_supplicant v1.0
> Copyright (c) 2003-2012, Jouni Malinen <j@w1.fi> and contributors
>
> Debian version: 1.0-3+b2
>
> Please note: during all the following experiments at times
> two other computers (iPhone, WinXP) very connected without
> any problems (of course on different IPs).
>
>
So this section seems to indicate that the access point is ignoring
your probe requests:
> ad 1) during connection permanent break off
> ============================================
>
> typical dmesg output:
> many times:
> May 8 20:54:59 tofuschnitzel NetworkManager[4878]: <info> (wlan0):
> supplicant interface state: disconnected -> scanning
> May 8 20:54:59 tofuschnitzel wpa_supplicant[5513]: wlan0: SME: Trying to
> authenticate with 00:3a:9d:b4:54:5a (SSID='norbujp' fr
> eq=2447 MHz)
> kernel: [19070.021021] wlan0: authenticate with 00:3a:9d:b4:54:5a
> NetworkManager[4878]: <info> (wlan0): supplicant interface state: scanning
> -> authenticating
> kernel: [19070.040313] wlan0: send auth to 00:3a:9d:b4:54:5a (try 1/3)
> kernel: [19070.144143] wlan0: send auth to 00:3a:9d:b4:54:5a (try 2/3)
> kernel: [19070.248113] wlan0: send auth to 00:3a:9d:b4:54:5a (try 3/3)
> wpa_supplicant[5513]: wlan0: Trying to associate with 00:3a:9d:b4:54:5a
> (SSID='norbujp' freq=2447 MHz)
> kernel: [19070.286906] wlan0: authenticated
> kernel: [19070.288224] wlan0: associate with 00:3a:9d:b4:54:5a (try 1/3)
> NetworkManager[4878]: <info> (wlan0): supplicant interface state:
> authenticating -> associating
> kernel: [19070.392185] wlan0: associate with 00:3a:9d:b4:54:5a (try 2/3)
> kernel: [19070.496204] wlan0: associate with 00:3a:9d:b4:54:5a (try 3/3)
> kernel: [19070.600253] wlan0: association with 00:3a:9d:b4:54:5a timed out
> NetworkManager[4878]: <info> (wlan0): supplicant interface state:
> associating -> disconnected
If that is happening for your client somehow, wpa_supplicant won't
work well. :-)
I understand that you have other clients on the same WLAN, but what is
your wireless infrastructure? The MAC OID of your BSSID comes back as
"NecAcces" - but I'm not familiar with that vendor. Also, do you have
a WLAN packet capture (from another host nearby on the same channel)?
That would be helpful as well.
--
Matt
^ permalink raw reply
* Re: pull request: wireless 2013-05-10
From: David Miller @ 2013-05-10 16:44 UTC (permalink / raw)
To: linville; +Cc: linux-wireless, netdev, linux-kernel
In-Reply-To: <20130510152202.GD2103@tuxdriver.com>
From: "John W. Linville" <linville@tuxdriver.com>
Date: Fri, 10 May 2013 11:22:02 -0400
> Here is a batch of fixes intended for the 3.10 stream.
...
> Please let me know if there are problems!
...
> git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
Pulled, thanks John!
^ permalink raw reply
* implement admission control algorithm
From: Cyril @ 2013-05-10 16:37 UTC (permalink / raw)
To: linux-wireless
Hello,
I am a student in thesis and my work brings me to use ath9k driver and
hostapd.
I am currently working to enhance video streaming on 802.11 WLAN with Quality
Of Service by implement a call admission control algorithm.
So I need to modify the hostapd source code or aht9k source code to add a
function for the admission control for new stations.
But I don't know where I have to implement this function and where I need to
call it to works well...
If someone could help me, I would be grateful.
Thanks,
Cyril S.
^ permalink raw reply
* pull request: wireless 2013-05-10
From: John W. Linville @ 2013-05-10 15:22 UTC (permalink / raw)
To: davem; +Cc: linux-wireless, netdev, linux-kernel
[-- Attachment #1: Type: text/plain, Size: 24426 bytes --]
Dave,
Here is a batch of fixes intended for the 3.10 stream.
Amitkumar Karwar provides an mwifiex fix to plug a memory leak when
the driver is unloaded.
Bing Zhao brings an mwifiex fix for some flag handling that leads to
log spam and an unusable interface.
Daniel Drake offers an mwifiex fix for multicast filter setup, to
correctly implement wakeup behaviour for multicast WOL.
Felix Fietkau fixes an ath9k problem that produces logspam and keycache
errors due to a bad return code.
Stanislaw Gruszka produces an fix for a WARNING from ath5k, and an
iwl4965 workaround to stop advertising a feature that doesn't work with
the current mac80211 implementation.
Sujith Manoharan gives us an ath9k fix to reprogram the HW beacon timers
after a TSF update, and an initvals fix for the AR9565 device.
Thommy Jakobsson fixes an rx descriptor underrun on b43.
Please let me know if there are problems!
John
---
The following changes since commit 70eba4226d9718946941c7be0c8cb66d431e7686:
Merge tag 'please-pull-pstore' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux (2013-05-09 16:42:10 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless.git for-davem
for you to fetch changes up to 4f81d715b90b7ebe049dd906511c47956086ad44:
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless into for-davem (2013-05-10 10:29:24 -0400)
----------------------------------------------------------------
Amitkumar Karwar (1):
mwifiex: fix memory leak issue when driver unload
Bing Zhao (1):
mwifiex: clear is_suspended flag when interrupt is received early
Daniel Drake (1):
mwifiex: fix setting of multicast filter
Felix Fietkau (1):
ath9k: fix key allocation error handling for powersave keys
John W. Linville (1):
Merge branch 'master' of git://git.kernel.org/.../linville/wireless into for-davem
Stanislaw Gruszka (2):
ath5k: do not reschedule tx_complete_work on stop
iwl4965: workaround connection regression on passive channel
Sujith Manoharan (2):
ath9k: Fix beacon reconfiguration
ath9k: Update initvals for AR9565
Thommy Jakobsson (1):
B43: Handle DMA RX descriptor underrun
drivers/net/wireless/ath/ath5k/base.c | 5 +
.../net/wireless/ath/ath9k/ar9565_1p0_initvals.h | 138 +++++++++++----------
drivers/net/wireless/ath/ath9k/main.c | 10 +-
drivers/net/wireless/b43/dma.c | 19 +++
drivers/net/wireless/b43/dma.h | 4 +-
drivers/net/wireless/b43/main.c | 43 +++----
drivers/net/wireless/iwlegacy/4965-mac.c | 3 +-
drivers/net/wireless/mwifiex/cfg80211.c | 3 -
drivers/net/wireless/mwifiex/cmdevt.c | 1 +
drivers/net/wireless/mwifiex/main.c | 1 +
drivers/net/wireless/mwifiex/sta_ioctl.c | 21 +---
11 files changed, 131 insertions(+), 117 deletions(-)
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 9b20d9e..7f702fe 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2369,6 +2369,9 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
int i;
bool needreset = false;
+ if (!test_bit(ATH_STAT_STARTED, ah->status))
+ return;
+
mutex_lock(&ah->lock);
for (i = 0; i < ARRAY_SIZE(ah->txqs); i++) {
@@ -2676,6 +2679,7 @@ done:
mmiowb();
mutex_unlock(&ah->lock);
+ set_bit(ATH_STAT_STARTED, ah->status);
ieee80211_queue_delayed_work(ah->hw, &ah->tx_complete_work,
msecs_to_jiffies(ATH5K_TX_COMPLETE_POLL_INT));
@@ -2737,6 +2741,7 @@ void ath5k_stop(struct ieee80211_hw *hw)
ath5k_stop_tasklets(ah);
+ clear_bit(ATH_STAT_STARTED, ah->status);
cancel_delayed_work_sync(&ah->tx_complete_work);
if (!ath5k_modparam_no_hw_rfkill_switch)
diff --git a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
index 0c2ac0c..e85a8b0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9565_1p0_initvals.h
@@ -233,9 +233,9 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
{0x00009d10, 0x01834061},
{0x00009d14, 0x00c00400},
{0x00009d18, 0x00000000},
- {0x00009e08, 0x0078230c},
- {0x00009e24, 0x990bb515},
- {0x00009e28, 0x126f0000},
+ {0x00009e08, 0x0038230c},
+ {0x00009e24, 0x9907b515},
+ {0x00009e28, 0x126f0600},
{0x00009e30, 0x06336f77},
{0x00009e34, 0x6af6532f},
{0x00009e38, 0x0cc80c00},
@@ -337,7 +337,7 @@ static const u32 ar9565_1p0_baseband_core[][2] = {
static const u32 ar9565_1p0_baseband_postamble[][5] = {
/* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
- {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a800d},
+ {0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8009},
{0x00009820, 0x206a022e, 0x206a022e, 0x206a012e, 0x206a01ae},
{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x63c640da},
{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x09143c81},
@@ -345,9 +345,9 @@ static const u32 ar9565_1p0_baseband_postamble[][5] = {
{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
{0x00009c00, 0x000000c4, 0x000000c4, 0x000000c4, 0x000000c4},
{0x00009e00, 0x0372111a, 0x0372111a, 0x037216a0, 0x037216a0},
- {0x00009e04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
- {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000d8},
- {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec86d2e},
+ {0x00009e04, 0x00802020, 0x00802020, 0x00142020, 0x00142020},
+ {0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+ {0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec84d2e, 0x7ec84d2e},
{0x00009e14, 0x37b95d5e, 0x37b9605e, 0x3379605e, 0x33795d5e},
{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
@@ -450,6 +450,8 @@ static const u32 ar9565_1p0_soc_postamble[][5] = {
static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
/* Addr allmodes */
+ {0x00004050, 0x00300300},
+ {0x0000406c, 0x00100000},
{0x0000a000, 0x00010000},
{0x0000a004, 0x00030002},
{0x0000a008, 0x00050004},
@@ -498,27 +500,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
{0x0000a0b4, 0x00000000},
{0x0000a0b8, 0x00000000},
{0x0000a0bc, 0x00000000},
- {0x0000a0c0, 0x001f0000},
- {0x0000a0c4, 0x01000101},
- {0x0000a0c8, 0x011e011f},
- {0x0000a0cc, 0x011c011d},
- {0x0000a0d0, 0x02030204},
- {0x0000a0d4, 0x02010202},
- {0x0000a0d8, 0x021f0200},
- {0x0000a0dc, 0x0302021e},
- {0x0000a0e0, 0x03000301},
- {0x0000a0e4, 0x031e031f},
- {0x0000a0e8, 0x0402031d},
- {0x0000a0ec, 0x04000401},
- {0x0000a0f0, 0x041e041f},
- {0x0000a0f4, 0x0502041d},
- {0x0000a0f8, 0x05000501},
- {0x0000a0fc, 0x051e051f},
- {0x0000a100, 0x06010602},
- {0x0000a104, 0x061f0600},
- {0x0000a108, 0x061d061e},
- {0x0000a10c, 0x07020703},
- {0x0000a110, 0x07000701},
+ {0x0000a0c0, 0x00bf00a0},
+ {0x0000a0c4, 0x11a011a1},
+ {0x0000a0c8, 0x11be11bf},
+ {0x0000a0cc, 0x11bc11bd},
+ {0x0000a0d0, 0x22632264},
+ {0x0000a0d4, 0x22612262},
+ {0x0000a0d8, 0x227f2260},
+ {0x0000a0dc, 0x4322227e},
+ {0x0000a0e0, 0x43204321},
+ {0x0000a0e4, 0x433e433f},
+ {0x0000a0e8, 0x4462433d},
+ {0x0000a0ec, 0x44604461},
+ {0x0000a0f0, 0x447e447f},
+ {0x0000a0f4, 0x5582447d},
+ {0x0000a0f8, 0x55805581},
+ {0x0000a0fc, 0x559e559f},
+ {0x0000a100, 0x66816682},
+ {0x0000a104, 0x669f6680},
+ {0x0000a108, 0x669d669e},
+ {0x0000a10c, 0x77627763},
+ {0x0000a110, 0x77607761},
{0x0000a114, 0x00000000},
{0x0000a118, 0x00000000},
{0x0000a11c, 0x00000000},
@@ -530,27 +532,27 @@ static const u32 ar9565_1p0_Common_rx_gain_table[][2] = {
{0x0000a134, 0x00000000},
{0x0000a138, 0x00000000},
{0x0000a13c, 0x00000000},
- {0x0000a140, 0x001f0000},
- {0x0000a144, 0x01000101},
- {0x0000a148, 0x011e011f},
- {0x0000a14c, 0x011c011d},
- {0x0000a150, 0x02030204},
- {0x0000a154, 0x02010202},
- {0x0000a158, 0x021f0200},
- {0x0000a15c, 0x0302021e},
- {0x0000a160, 0x03000301},
- {0x0000a164, 0x031e031f},
- {0x0000a168, 0x0402031d},
- {0x0000a16c, 0x04000401},
- {0x0000a170, 0x041e041f},
- {0x0000a174, 0x0502041d},
- {0x0000a178, 0x05000501},
- {0x0000a17c, 0x051e051f},
- {0x0000a180, 0x06010602},
- {0x0000a184, 0x061f0600},
- {0x0000a188, 0x061d061e},
- {0x0000a18c, 0x07020703},
- {0x0000a190, 0x07000701},
+ {0x0000a140, 0x00bf00a0},
+ {0x0000a144, 0x11a011a1},
+ {0x0000a148, 0x11be11bf},
+ {0x0000a14c, 0x11bc11bd},
+ {0x0000a150, 0x22632264},
+ {0x0000a154, 0x22612262},
+ {0x0000a158, 0x227f2260},
+ {0x0000a15c, 0x4322227e},
+ {0x0000a160, 0x43204321},
+ {0x0000a164, 0x433e433f},
+ {0x0000a168, 0x4462433d},
+ {0x0000a16c, 0x44604461},
+ {0x0000a170, 0x447e447f},
+ {0x0000a174, 0x5582447d},
+ {0x0000a178, 0x55805581},
+ {0x0000a17c, 0x559e559f},
+ {0x0000a180, 0x66816682},
+ {0x0000a184, 0x669f6680},
+ {0x0000a188, 0x669d669e},
+ {0x0000a18c, 0x77e677e7},
+ {0x0000a190, 0x77e477e5},
{0x0000a194, 0x00000000},
{0x0000a198, 0x00000000},
{0x0000a19c, 0x00000000},
@@ -770,7 +772,7 @@ static const u32 ar9565_1p0_Modes_lowest_ob_db_tx_gain_table[][5] = {
static const u32 ar9565_1p0_pciephy_clkreq_disable_L1[][2] = {
/* Addr allmodes */
- {0x00018c00, 0x18213ede},
+ {0x00018c00, 0x18212ede},
{0x00018c04, 0x000801d8},
{0x00018c08, 0x0003780c},
};
@@ -889,8 +891,8 @@ static const u32 ar9565_1p0_common_wo_xlna_rx_gain_table[][2] = {
{0x0000a180, 0x66816682},
{0x0000a184, 0x669f6680},
{0x0000a188, 0x669d669e},
- {0x0000a18c, 0x77627763},
- {0x0000a190, 0x77607761},
+ {0x0000a18c, 0x77e677e7},
+ {0x0000a190, 0x77e477e5},
{0x0000a194, 0x00000000},
{0x0000a198, 0x00000000},
{0x0000a19c, 0x00000000},
@@ -1114,7 +1116,7 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
{0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
{0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
{0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
{0x0000a508, 0x0b022220, 0x0b022220, 0x08000004, 0x08000004},
@@ -1140,13 +1142,13 @@ static const u32 ar9565_1p0_modes_high_ob_db_tx_gain_table[][5] = {
{0x0000a558, 0x69027f56, 0x69027f56, 0x53001ce5, 0x53001ce5},
{0x0000a55c, 0x6d029f56, 0x6d029f56, 0x57001ce9, 0x57001ce9},
{0x0000a560, 0x73049f56, 0x73049f56, 0x5b001ceb, 0x5b001ceb},
- {0x0000a564, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
- {0x0000a568, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
- {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
- {0x0000a570, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
- {0x0000a574, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
- {0x0000a578, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
- {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x5d001eec, 0x5d001eec},
+ {0x0000a564, 0x7804ff56, 0x7804ff56, 0x60001cf0, 0x60001cf0},
+ {0x0000a568, 0x7804ff56, 0x7804ff56, 0x61001cf1, 0x61001cf1},
+ {0x0000a56c, 0x7804ff56, 0x7804ff56, 0x62001cf2, 0x62001cf2},
+ {0x0000a570, 0x7804ff56, 0x7804ff56, 0x63001cf3, 0x63001cf3},
+ {0x0000a574, 0x7804ff56, 0x7804ff56, 0x64001cf4, 0x64001cf4},
+ {0x0000a578, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
+ {0x0000a57c, 0x7804ff56, 0x7804ff56, 0x66001ff6, 0x66001ff6},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
@@ -1174,7 +1176,7 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
{0x0000a2e0, 0xffecec00, 0xffecec00, 0xfd339c84, 0xfd339c84},
{0x0000a2e4, 0xfc0f0000, 0xfc0f0000, 0xfec3e000, 0xfec3e000},
{0x0000a2e8, 0xfc100000, 0xfc100000, 0xfffc0000, 0xfffc0000},
- {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
+ {0x0000a410, 0x000050d9, 0x000050d9, 0x000050df, 0x000050df},
{0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000},
{0x0000a504, 0x06002223, 0x06002223, 0x04000002, 0x04000002},
{0x0000a508, 0x0a022220, 0x0a022220, 0x08000004, 0x08000004},
@@ -1200,13 +1202,13 @@ static const u32 ar9565_1p0_modes_high_power_tx_gain_table[][5] = {
{0x0000a558, 0x66027f56, 0x66027f56, 0x4c001ce5, 0x4c001ce5},
{0x0000a55c, 0x6a029f56, 0x6a029f56, 0x50001ce9, 0x50001ce9},
{0x0000a560, 0x70049f56, 0x70049f56, 0x54001ceb, 0x54001ceb},
- {0x0000a564, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a568, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a570, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a574, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a578, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
- {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x56001eec, 0x56001eec},
+ {0x0000a564, 0x7504ff56, 0x7504ff56, 0x59001cf0, 0x59001cf0},
+ {0x0000a568, 0x7504ff56, 0x7504ff56, 0x5a001cf1, 0x5a001cf1},
+ {0x0000a56c, 0x7504ff56, 0x7504ff56, 0x5b001cf2, 0x5b001cf2},
+ {0x0000a570, 0x7504ff56, 0x7504ff56, 0x5c001cf3, 0x5c001cf3},
+ {0x0000a574, 0x7504ff56, 0x7504ff56, 0x5d001cf4, 0x5d001cf4},
+ {0x0000a578, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
+ {0x0000a57c, 0x7504ff56, 0x7504ff56, 0x5f001ff6, 0x5f001ff6},
{0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
{0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6963862..a18414b 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -227,13 +227,13 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start)
if (!test_bit(SC_OP_BEACONS, &sc->sc_flags))
goto work;
- ath9k_set_beacon(sc);
-
if (ah->opmode == NL80211_IFTYPE_STATION &&
test_bit(SC_OP_PRIM_STA_VIF, &sc->sc_flags)) {
spin_lock_irqsave(&sc->sc_pm_lock, flags);
sc->ps_flags |= PS_BEACON_SYNC | PS_WAIT_FOR_BEACON;
spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ } else {
+ ath9k_set_beacon(sc);
}
work:
ath_restart_work(sc);
@@ -1332,6 +1332,7 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ath_node *an = (struct ath_node *) sta->drv_priv;
struct ieee80211_key_conf ps_key = { };
+ int key;
ath_node_attach(sc, sta, vif);
@@ -1339,7 +1340,9 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
vif->type != NL80211_IFTYPE_AP_VLAN)
return 0;
- an->ps_key = ath_key_config(common, vif, sta, &ps_key);
+ key = ath_key_config(common, vif, sta, &ps_key);
+ if (key > 0)
+ an->ps_key = key;
return 0;
}
@@ -1356,6 +1359,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc,
return;
ath_key_delete(common, &ps_key);
+ an->ps_key = 0;
}
static int ath9k_sta_remove(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/b43/dma.c b/drivers/net/wireless/b43/dma.c
index 523355b..f7c70b3 100644
--- a/drivers/net/wireless/b43/dma.c
+++ b/drivers/net/wireless/b43/dma.c
@@ -1728,6 +1728,25 @@ drop_recycle_buffer:
sync_descbuffer_for_device(ring, dmaaddr, ring->rx_buffersize);
}
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring)
+{
+ int current_slot, previous_slot;
+
+ B43_WARN_ON(ring->tx);
+
+ /* Device has filled all buffers, drop all packets and let TCP
+ * decrease speed.
+ * Decrement RX index by one will let the device to see all slots
+ * as free again
+ */
+ /*
+ *TODO: How to increase rx_drop in mac80211?
+ */
+ current_slot = ring->ops->get_current_rxslot(ring);
+ previous_slot = prev_slot(ring, current_slot);
+ ring->ops->set_current_rxslot(ring, previous_slot);
+}
+
void b43_dma_rx(struct b43_dmaring *ring)
{
const struct b43_dma_ops *ops = ring->ops;
diff --git a/drivers/net/wireless/b43/dma.h b/drivers/net/wireless/b43/dma.h
index 9fdd198..df8c8cd 100644
--- a/drivers/net/wireless/b43/dma.h
+++ b/drivers/net/wireless/b43/dma.h
@@ -9,7 +9,7 @@
/* DMA-Interrupt reasons. */
#define B43_DMAIRQ_FATALMASK ((1 << 10) | (1 << 11) | (1 << 12) \
| (1 << 14) | (1 << 15))
-#define B43_DMAIRQ_NONFATALMASK (1 << 13)
+#define B43_DMAIRQ_RDESC_UFLOW (1 << 13)
#define B43_DMAIRQ_RX_DONE (1 << 16)
/*** 32-bit DMA Engine. ***/
@@ -295,6 +295,8 @@ int b43_dma_tx(struct b43_wldev *dev,
void b43_dma_handle_txstatus(struct b43_wldev *dev,
const struct b43_txstatus *status);
+void b43_dma_handle_rx_overflow(struct b43_dmaring *ring);
+
void b43_dma_rx(struct b43_dmaring *ring);
void b43_dma_direct_fifo_rx(struct b43_wldev *dev,
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index d377f77..6dd07e2 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -1902,30 +1902,18 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
}
}
- if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK |
- B43_DMAIRQ_NONFATALMASK))) {
- if (merged_dma_reason & B43_DMAIRQ_FATALMASK) {
- b43err(dev->wl, "Fatal DMA error: "
- "0x%08X, 0x%08X, 0x%08X, "
- "0x%08X, 0x%08X, 0x%08X\n",
- dma_reason[0], dma_reason[1],
- dma_reason[2], dma_reason[3],
- dma_reason[4], dma_reason[5]);
- b43err(dev->wl, "This device does not support DMA "
+ if (unlikely(merged_dma_reason & (B43_DMAIRQ_FATALMASK))) {
+ b43err(dev->wl,
+ "Fatal DMA error: 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X, 0x%08X\n",
+ dma_reason[0], dma_reason[1],
+ dma_reason[2], dma_reason[3],
+ dma_reason[4], dma_reason[5]);
+ b43err(dev->wl, "This device does not support DMA "
"on your system. It will now be switched to PIO.\n");
- /* Fall back to PIO transfers if we get fatal DMA errors! */
- dev->use_pio = true;
- b43_controller_restart(dev, "DMA error");
- return;
- }
- if (merged_dma_reason & B43_DMAIRQ_NONFATALMASK) {
- b43err(dev->wl, "DMA error: "
- "0x%08X, 0x%08X, 0x%08X, "
- "0x%08X, 0x%08X, 0x%08X\n",
- dma_reason[0], dma_reason[1],
- dma_reason[2], dma_reason[3],
- dma_reason[4], dma_reason[5]);
- }
+ /* Fall back to PIO transfers if we get fatal DMA errors! */
+ dev->use_pio = true;
+ b43_controller_restart(dev, "DMA error");
+ return;
}
if (unlikely(reason & B43_IRQ_UCODE_DEBUG))
@@ -1944,6 +1932,11 @@ static void b43_do_interrupt_thread(struct b43_wldev *dev)
handle_irq_noise(dev);
/* Check the DMA reason registers for received data. */
+ if (dma_reason[0] & B43_DMAIRQ_RDESC_UFLOW) {
+ if (B43_DEBUG)
+ b43warn(dev->wl, "RX descriptor underrun\n");
+ b43_dma_handle_rx_overflow(dev->dma.rx_ring);
+ }
if (dma_reason[0] & B43_DMAIRQ_RX_DONE) {
if (b43_using_pio_transfers(dev))
b43_pio_rx(dev->pio.rx_queue);
@@ -2001,7 +1994,7 @@ static irqreturn_t b43_do_interrupt(struct b43_wldev *dev)
return IRQ_NONE;
dev->dma_reason[0] = b43_read32(dev, B43_MMIO_DMA0_REASON)
- & 0x0001DC00;
+ & 0x0001FC00;
dev->dma_reason[1] = b43_read32(dev, B43_MMIO_DMA1_REASON)
& 0x0000DC00;
dev->dma_reason[2] = b43_read32(dev, B43_MMIO_DMA2_REASON)
@@ -3130,7 +3123,7 @@ static int b43_chip_init(struct b43_wldev *dev)
b43_write32(dev, 0x018C, 0x02000000);
}
b43_write32(dev, B43_MMIO_GEN_IRQ_REASON, 0x00004000);
- b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001DC00);
+ b43_write32(dev, B43_MMIO_DMA0_IRQ_MASK, 0x0001FC00);
b43_write32(dev, B43_MMIO_DMA1_IRQ_MASK, 0x0000DC00);
b43_write32(dev, B43_MMIO_DMA2_IRQ_MASK, 0x0000DC00);
b43_write32(dev, B43_MMIO_DMA3_IRQ_MASK, 0x0001DC00);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index b8f82e6..9a95045 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5741,8 +5741,7 @@ il4965_mac_setup_register(struct il_priv *il, u32 max_probe_length)
hw->flags =
IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC | IEEE80211_HW_SPECTRUM_MGMT |
- IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_SUPPORTS_PS |
- IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
+ IEEE80211_HW_SUPPORTS_PS | IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
if (il->cfg->sku & IL_SKU_N)
hw->flags |=
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index d3c8ece..e42b266 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -2234,9 +2234,6 @@ int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev)
if (wdev->netdev->reg_state == NETREG_REGISTERED)
unregister_netdevice(wdev->netdev);
- if (wdev->netdev->reg_state == NETREG_UNREGISTERED)
- free_netdev(wdev->netdev);
-
/* Clear the priv in adapter */
priv->netdev = NULL;
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 74db0d2..26755d9 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -1191,6 +1191,7 @@ mwifiex_process_hs_config(struct mwifiex_adapter *adapter)
adapter->if_ops.wakeup(adapter);
adapter->hs_activated = false;
adapter->is_hs_configured = false;
+ adapter->is_suspended = false;
mwifiex_hs_activated_event(mwifiex_get_priv(adapter,
MWIFIEX_BSS_ROLE_ANY),
false);
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 121443a..2eb88ea 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -655,6 +655,7 @@ void mwifiex_init_priv_params(struct mwifiex_private *priv,
struct net_device *dev)
{
dev->netdev_ops = &mwifiex_netdev_ops;
+ dev->destructor = free_netdev;
/* Initialize private structure */
priv->current_key_index = 0;
priv->media_connected = false;
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index 311d0b2..1a8a19d 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -96,7 +96,7 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
} else {
/* Multicast */
priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE;
- if (mcast_list->mode == MWIFIEX_MULTICAST_MODE) {
+ if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) {
dev_dbg(priv->adapter->dev,
"info: Enabling All Multicast!\n");
priv->curr_pkt_filter |=
@@ -108,20 +108,11 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
dev_dbg(priv->adapter->dev,
"info: Set multicast list=%d\n",
mcast_list->num_multicast_addr);
- /* Set multicast addresses to firmware */
- if (old_pkt_filter == priv->curr_pkt_filter) {
- /* Send request to firmware */
- ret = mwifiex_send_cmd_async(priv,
- HostCmd_CMD_MAC_MULTICAST_ADR,
- HostCmd_ACT_GEN_SET, 0,
- mcast_list);
- } else {
- /* Send request to firmware */
- ret = mwifiex_send_cmd_async(priv,
- HostCmd_CMD_MAC_MULTICAST_ADR,
- HostCmd_ACT_GEN_SET, 0,
- mcast_list);
- }
+ /* Send multicast addresses to firmware */
+ ret = mwifiex_send_cmd_async(priv,
+ HostCmd_CMD_MAC_MULTICAST_ADR,
+ HostCmd_ACT_GEN_SET, 0,
+ mcast_list);
}
}
}
--
John W. Linville Someday the world will need a hero, and you
linville@tuxdriver.com might be all we have. Be ready.
[-- Attachment #2: Type: application/pgp-signature, Size: 836 bytes --]
^ permalink raw reply related
* Re: [RFC 0/4] cfg80211/mac80211: simplify locking
From: Johannes Berg @ 2013-05-10 14:27 UTC (permalink / raw)
To: Ben Greear; +Cc: linux-wireless
In-Reply-To: <518D0390.90006@candelatech.com>
On Fri, 2013-05-10 at 07:26 -0700, Ben Greear wrote:
> On 05/10/2013 05:08 AM, Johannes Berg wrote:
> > I got a little fed up with all the locking, and decided to simplify.
> >
> > This should still work, but I've only done some very simple tests.
> > I'm hoping it'll fix some of the weird corner cases that Ben and
> > others have found, which may be due to different locks in different
> > cases and things racing against each other ... I'm not convinced it
> > really will though, but hey, who knows :)
>
> I'm stacked high with tasks at the moment, but will try to
> run this through some testing soon.
>
> These are in your tree?
In the wip branch, for now.
johannes
^ permalink raw reply
* Re: [RFC 0/4] cfg80211/mac80211: simplify locking
From: Ben Greear @ 2013-05-10 14:26 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
On 05/10/2013 05:08 AM, Johannes Berg wrote:
> I got a little fed up with all the locking, and decided to simplify.
>
> This should still work, but I've only done some very simple tests.
> I'm hoping it'll fix some of the weird corner cases that Ben and
> others have found, which may be due to different locks in different
> cases and things racing against each other ... I'm not convinced it
> really will though, but hey, who knows :)
I'm stacked high with tasks at the moment, but will try to
run this through some testing soon.
These are in your tree?
Thanks,
Ben
>
> johannes
>
--
Ben Greear <greearb@candelatech.com>
Candela Technologies Inc http://www.candelatech.com
^ permalink raw reply
* [PATCH] mac80211: enable power save only if DTIM period is available
From: Johannes Berg @ 2013-05-10 14:10 UTC (permalink / raw)
To: linux-wireless; +Cc: Alexander Bondar
From: Alexander Bondar <alexander.bondar@intel.com>
Generally, the DTIM period is available after a beacon has
been received, and if no beacon has been received enabling
powersave is problematic anyway for synchronisation. Since
some drivers may require the DTIM period for powersave,
don't enable powersave until it becomes available in case
the scan/association managed to not receive a beacon.
Signed-off-by: Alexander Bondar <alexander.bondar@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/mac80211/mlme.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 2bfcdda..07a3eb5 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1390,6 +1390,9 @@ static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
IEEE80211_STA_CONNECTION_POLL))
return false;
+ if (!sdata->vif.bss_conf.dtim_period)
+ return false;
+
rcu_read_lock();
sta = sta_info_get(sdata, mgd->bssid);
if (sta)
@@ -3126,6 +3129,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
changed |= BSS_CHANGED_DTIM_PERIOD;
+ ieee80211_recalc_ps_vif(sdata);
}
if (elems.erp_info) {
--
1.8.0
^ permalink raw reply related
* [RFC v2 4/4] cfg80211/mac80211: use cfg80211 wdev mutex in mac80211
From: Johannes Berg @ 2013-05-10 13:43 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368193436-26618-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Using separate locks in cfg80211 and mac80211 has always
caused issues, for example having to unlock in places in
mac80211 to call cfg80211, which even needed a framework
to make cfg80211 calls after some functions returned etc.
Additionally, I suspect some issues people have reported
with the cfg80211 state getting confused could be due to
such issues, when cfg80211 is asking mac80211 to change
state but mac80211 is in the process of telling cfg80211
that the state changed (in another way.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
Documentation/DocBook/80211.tmpl | 2 -
include/net/cfg80211.h | 41 ++---
net/mac80211/cfg.c | 4 +-
net/mac80211/debugfs_netdev.c | 10 +-
net/mac80211/ht.c | 4 +-
net/mac80211/ibss.c | 39 ++---
net/mac80211/ieee80211_i.h | 25 ++-
net/mac80211/main.c | 4 +-
net/mac80211/mesh.c | 32 ++--
net/mac80211/mesh_plink.c | 7 +-
net/mac80211/mlme.c | 333 ++++++++++++++-------------------------
net/mac80211/util.c | 4 +-
net/wireless/mlme.c | 48 +-----
net/wireless/trace.h | 4 +-
14 files changed, 206 insertions(+), 351 deletions(-)
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 0f6a3ed..ebe8969 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -132,9 +132,7 @@
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
!Finclude/net/cfg80211.h cfg80211_send_deauth
-!Finclude/net/cfg80211.h __cfg80211_send_deauth
!Finclude/net/cfg80211.h cfg80211_send_disassoc
-!Finclude/net/cfg80211.h __cfg80211_send_disassoc
!Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_roamed
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 085e5f7..0959fed 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2849,7 +2849,8 @@ struct cfg80211_cached_keys;
* by cfg80211 on change_interface
* @mgmt_registrations: list of registrations for management frames
* @mgmt_registrations_lock: lock for the list
- * @mtx: mutex used to lock data in this struct
+ * @mtx: mutex used to lock data in this struct, may be used by drivers
+ * and some API functions require it held
* @cleanup_work: work struct used for cleanup that can't be done directly
* @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid
@@ -3413,7 +3414,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
* This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
- * call. This function may sleep.
+ * call. This function may sleep. The caller must hold the corresponding wdev's
+ * mutex.
*/
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
@@ -3422,7 +3424,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
*
- * This function may sleep.
+ * This function may sleep. The caller must hold the corresponding wdev's
+ * mutex.
*/
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
@@ -3437,7 +3440,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
* This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of
- * cfg80211_ops::assoc() call. This function may sleep.
+ * cfg80211_ops::assoc() call. This function may sleep. The caller must hold
+ * the corresponding wdev's mutex.
*/
void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
const u8 *buf, size_t len);
@@ -3447,7 +3451,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* @dev: network device
* @addr: The MAC address of the device with which the association timed out
*
- * This function may sleep.
+ * This function may sleep. The caller must hold the corresponding wdev's mutex.
*/
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
@@ -3459,21 +3463,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
*
* This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and
- * locally generated ones. This function may sleep.
+ * locally generated ones. This function may sleep. The caller must hold the
+ * corresponding wdev's mutex.
*/
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
/**
- * __cfg80211_send_deauth - notification of processed deauthentication
- * @dev: network device
- * @buf: deauthentication frame (header + body)
- * @len: length of the frame data
- *
- * Like cfg80211_send_deauth(), but doesn't take the wdev lock.
- */
-void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
-
-/**
* cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
@@ -3481,22 +3476,12 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
*
* This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally
- * generated ones. This function may sleep.
+ * generated ones. This function may sleep. The caller must hold the
+ * corresponding wdev's mutex.
*/
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
/**
- * __cfg80211_send_disassoc - notification of processed disassociation
- * @dev: network device
- * @buf: disassociation response frame (header + body)
- * @len: length of the frame data
- *
- * Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
- */
-void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
- size_t len);
-
-/**
* cfg80211_send_unprot_deauth - notification of unprotected deauthentication
* @dev: network device
* @buf: deauthentication frame (header + body)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6698945..a8e4ba1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2317,7 +2317,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode old_req;
int err;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ lockdep_assert_held(&sdata->wdev.mtx);
old_req = sdata->u.mgd.req_smps;
sdata->u.mgd.req_smps = smps_mode;
@@ -2374,9 +2374,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
local->dynamic_ps_forced_timeout = timeout;
/* no change, but if automatic follow powersave */
- mutex_lock(&sdata->u.mgd.mtx);
__ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
- mutex_unlock(&sdata->u.mgd.mtx);
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 14abcf4..27d08ec 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
err = __ieee80211_request_smps(sdata, smps_mode);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
return err;
}
@@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
case NL80211_IFTYPE_STATION:
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
if (!sdata->u.mgd.associated) {
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
dev_kfree_skb(skb);
return -ENOTCONN;
}
memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr->addr3, addr, ETH_ALEN);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
break;
default:
dev_kfree_skb(skb);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index af8cee0..75dff33 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work)
container_of(work, struct ieee80211_sub_if_data,
u.mgd.request_smps_work);
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
}
void ieee80211_request_smps(struct ieee80211_vif *vif,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 170f9a7..3b305f3 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
int frame_len;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local, sdata);
@@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&ifibss->mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
rcu_assign_pointer(ifibss->presp, NULL);
if (presp)
kfree_rcu(presp, rcu_head);
@@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_bss_ies *ies;
u64 tsf;
- lockdep_assert_held(&sdata->u.ibss.mtx);
+ sdata_assert_lock(sdata);
if (beacon_int < 10)
beacon_int = 10;
@@ -408,7 +408,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- lockdep_assert_held(&sdata->u.ibss.mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 6)
return;
@@ -673,7 +673,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
int active = 0;
struct sta_info *sta;
- lockdep_assert_held(&sdata->u.ibss.mtx);
+ sdata_assert_lock(sdata);
rcu_read_lock();
@@ -699,7 +699,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
@@ -730,7 +730,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
u16 capability;
int i;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
if (ifibss->fixed_bssid) {
memcpy(bssid, ifibss->bssid, ETH_ALEN);
@@ -773,7 +773,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
int active_ibss;
u16 capability;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
active_ibss = ieee80211_sta_active_ibss(sdata);
ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
@@ -843,10 +843,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
u8 *pos, *end;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&ifibss->mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
len < 24 + 2 || !presp)
@@ -930,7 +930,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
- mutex_lock(&sdata->u.ibss.mtx);
+ sdata_lock(sdata);
if (!sdata->u.ibss.ssid_len)
goto mgmt_out; /* not ready to merge yet */
@@ -953,7 +953,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}
mgmt_out:
- mutex_unlock(&sdata->u.ibss.mtx);
+ sdata_unlock(sdata);
}
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
@@ -961,7 +961,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct sta_info *sta;
- mutex_lock(&ifibss->mtx);
+ sdata_lock(sdata);
/*
* Work could be scheduled after scan or similar
@@ -997,7 +997,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
}
out:
- mutex_unlock(&ifibss->mtx);
+ sdata_unlock(sdata);
}
static void ieee80211_ibss_timer(unsigned long data)
@@ -1014,7 +1014,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
- mutex_init(&ifibss->mtx);
INIT_LIST_HEAD(&ifibss->incomplete_stations);
spin_lock_init(&ifibss->incomplete_lock);
}
@@ -1041,8 +1040,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
{
u32 changed = 0;
- mutex_lock(&sdata->u.ibss.mtx);
-
if (params->bssid) {
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
sdata->u.ibss.fixed_bssid = true;
@@ -1075,8 +1072,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
sdata->u.ibss.ssid_len = params->ssid_len;
- mutex_unlock(&sdata->u.ibss.mtx);
-
/*
* 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
* reserved, but an HT STA shall protect HT transmissions as though
@@ -1112,8 +1107,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
struct sta_info *sta;
struct beacon_data *presp;
- mutex_lock(&sdata->u.ibss.mtx);
-
active_ibss = ieee80211_sta_active_ibss(sdata);
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -1157,7 +1150,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
/* remove beacon */
kfree(sdata->u.ibss.ie);
presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&sdata->u.ibss.mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
@@ -1173,7 +1166,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
del_timer_sync(&sdata->u.ibss.timer);
- mutex_unlock(&sdata->u.ibss.mtx);
-
return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 44be28cfc..2e75459 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -394,7 +394,6 @@ struct ieee80211_if_managed {
bool nullfunc_failed;
bool connection_loss;
- struct mutex mtx;
struct cfg80211_bss *associated;
struct ieee80211_mgd_auth_data *auth_data;
struct ieee80211_mgd_assoc_data *assoc_data;
@@ -488,8 +487,6 @@ struct ieee80211_if_managed {
struct ieee80211_if_ibss {
struct timer_list timer;
- struct mutex mtx;
-
unsigned long last_scan_completed;
u32 basic_rates;
@@ -580,8 +577,6 @@ struct ieee80211_if_mesh {
bool accepting_plinks;
int num_gates;
struct beacon_data __rcu *beacon;
- /* just protects beacon updates for now */
- struct mutex mtx;
const u8 *ie;
u8 ie_len;
enum {
@@ -778,6 +773,26 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
return container_of(p, struct ieee80211_sub_if_data, vif);
}
+static inline void sdata_lock(struct ieee80211_sub_if_data *sdata)
+ __acquires(&sdata->wdev.mtx)
+{
+ mutex_lock(&sdata->wdev.mtx);
+ __acquire(&sdata->wdev.mtx);
+}
+
+static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata)
+ __releases(&sdata->wdev.mtx)
+{
+ mutex_unlock(&sdata->wdev.mtx);
+ __release(&sdata->wdev.mtx);
+}
+
+static inline void
+sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
+{
+ lockdep_assert_held(&sdata->wdev.mtx);
+}
+
static inline enum ieee80211_band
ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8a7bfc4..1998f14 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -331,7 +331,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
return NOTIFY_DONE;
ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
/* Copy the addresses to the bss_conf list */
ifa = idev->ifa_list;
@@ -349,7 +349,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_ARP_FILTER);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return NOTIFY_DONE;
}
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 6952760..a430bc1 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -161,8 +161,11 @@ void mesh_sta_cleanup(struct sta_info *sta)
del_timer_sync(&sta->plink_timer);
}
- if (changed)
+ if (changed) {
+ sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);
+ sdata_unlock(sdata);
+ }
}
int mesh_rmc_init(struct ieee80211_sub_if_data *sdata)
@@ -577,7 +580,9 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata)
mesh_path_expire(sdata);
changed = mesh_accept_plinks_update(sdata);
+ sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);
+ sdata_unlock(sdata);
mod_timer(&ifmsh->housekeeping_timer,
round_jiffies(jiffies +
@@ -697,25 +702,21 @@ out_free:
}
static int
-ieee80211_mesh_rebuild_beacon(struct ieee80211_if_mesh *ifmsh)
+ieee80211_mesh_rebuild_beacon(struct ieee80211_sub_if_data *sdata)
{
struct beacon_data *old_bcn;
int ret;
- mutex_lock(&ifmsh->mtx);
-
- old_bcn = rcu_dereference_protected(ifmsh->beacon,
- lockdep_is_held(&ifmsh->mtx));
- ret = ieee80211_mesh_build_beacon(ifmsh);
+ old_bcn = rcu_dereference_protected(sdata->u.mesh.beacon,
+ lockdep_is_held(&sdata->wdev.mtx));
+ ret = ieee80211_mesh_build_beacon(&sdata->u.mesh);
if (ret)
/* just reuse old beacon */
- goto out;
+ return ret;
if (old_bcn)
kfree_rcu(old_bcn, rcu_head);
-out:
- mutex_unlock(&ifmsh->mtx);
- return ret;
+ return 0;
}
void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
@@ -726,7 +727,7 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
BSS_CHANGED_HT |
BSS_CHANGED_BASIC_RATES |
BSS_CHANGED_BEACON_INT)))
- if (ieee80211_mesh_rebuild_beacon(&sdata->u.mesh))
+ if (ieee80211_mesh_rebuild_beacon(sdata))
return;
ieee80211_bss_info_change_notify(sdata, changed);
}
@@ -788,12 +789,12 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata)
sdata->vif.bss_conf.enable_beacon = false;
clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
- mutex_lock(&ifmsh->mtx);
+ sdata_lock(sdata);
bcn = rcu_dereference_protected(ifmsh->beacon,
- lockdep_is_held(&ifmsh->mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
rcu_assign_pointer(ifmsh->beacon, NULL);
kfree_rcu(bcn, rcu_head);
- mutex_unlock(&ifmsh->mtx);
+ sdata_unlock(sdata);
/* flush STAs and mpaths on this iface */
sta_info_flush(sdata);
@@ -1041,7 +1042,6 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
spin_lock_init(&ifmsh->mesh_preq_queue_lock);
spin_lock_init(&ifmsh->sync_offset_lock);
RCU_INIT_POINTER(ifmsh->beacon, NULL);
- mutex_init(&ifmsh->mtx);
sdata->vif.bss_conf.bssid = zero_addr;
}
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c
index 09bebed..6c4da99 100644
--- a/net/mac80211/mesh_plink.c
+++ b/net/mac80211/mesh_plink.c
@@ -517,7 +517,9 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata,
ieee80211_mps_frame_release(sta, elems);
out:
rcu_read_unlock();
+ sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);
+ sdata_unlock(sdata);
}
static void mesh_plink_timer(unsigned long data)
@@ -1068,6 +1070,9 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata,
rcu_read_unlock();
- if (changed)
+ if (changed) {
+ sdata_lock(sdata);
ieee80211_mbss_info_change_notify(sdata, changed);
+ sdata_unlock(sdata);
+ }
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 07a3eb5..24a7f66 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -91,41 +91,6 @@ MODULE_PARM_DESC(probe_wait_ms,
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
/*
- * All cfg80211 functions have to be called outside a locked
- * section so that they can acquire a lock themselves... This
- * is much simpler than queuing up things in cfg80211, but we
- * do need some indirection for that here.
- */
-enum rx_mgmt_action {
- /* no action required */
- RX_MGMT_NONE,
-
- /* caller must call cfg80211_send_deauth() */
- RX_MGMT_CFG80211_DEAUTH,
-
- /* caller must call cfg80211_send_disassoc() */
- RX_MGMT_CFG80211_DISASSOC,
-
- /* caller must call cfg80211_send_rx_auth() */
- RX_MGMT_CFG80211_RX_AUTH,
-
- /* caller must call cfg80211_send_rx_assoc() */
- RX_MGMT_CFG80211_RX_ASSOC,
-
- /* caller must call cfg80211_send_assoc_timeout() */
- RX_MGMT_CFG80211_ASSOC_TIMEOUT,
-
- /* used when a processed beacon causes a deauth */
- RX_MGMT_CFG80211_TX_DEAUTH,
-};
-
-/* utils */
-static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
-{
- lockdep_assert_held(&ifmgd->mtx);
-}
-
-/*
* We can have multiple work items (and connection probing)
* scheduling this timer, but we need to take care to only
* reschedule it when it should fire _earlier_ than it was
@@ -135,13 +100,14 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
* has happened -- the work that runs from this timer will
* do that.
*/
-static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)
+static void run_again(struct ieee80211_sub_if_data *sdata,
+ unsigned long timeout)
{
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
- if (!timer_pending(&ifmgd->timer) ||
- time_before(timeout, ifmgd->timer.expires))
- mod_timer(&ifmgd->timer, timeout);
+ if (!timer_pending(&sdata->u.mgd.timer) ||
+ time_before(timeout, sdata->u.mgd.timer.expires))
+ mod_timer(&sdata->u.mgd.timer, timeout);
}
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
@@ -652,7 +618,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_channel *chan;
u32 rates = 0;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
@@ -962,7 +928,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if (!ieee80211_sdata_running(sdata))
return;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated)
goto out;
@@ -985,7 +951,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
IEEE80211_QUEUE_STOP_REASON_CSA);
out:
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1036,7 +1002,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_ht_operation *ht_oper;
int secondary_channel_offset = -1;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (!cbss)
return;
@@ -1845,7 +1811,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
u32 changed = 0;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (WARN_ON_ONCE(tx && !frame_buf))
return;
@@ -2054,7 +2020,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
}
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
- run_again(ifmgd, ifmgd->probe_timeout);
+ run_again(sdata, ifmgd->probe_timeout);
if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
ieee80211_flush_queues(sdata->local, sdata);
}
@@ -2068,7 +2034,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
if (!ieee80211_sdata_running(sdata))
return;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated)
goto out;
@@ -2122,7 +2088,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
ifmgd->probe_send_count = 0;
ieee80211_mgd_probe_ap_send(sdata);
out:
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
@@ -2138,7 +2104,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
return NULL;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (ifmgd->associated)
cbss = ifmgd->associated;
@@ -2171,9 +2137,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
@@ -2184,13 +2150,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
ieee80211_wake_queues_by_reason(&sdata->local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- mutex_unlock(&ifmgd->mtx);
- /*
- * must be outside lock due to cfg80211,
- * but that's not a problem.
- */
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
+ sdata_unlock(sdata);
}
static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -2257,7 +2219,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if (!assoc) {
sta_info_destroy_addr(sdata, auth_data->bss->bssid);
@@ -2298,27 +2260,26 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
auth_data->key_idx, tx_flags);
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 bssid[ETH_ALEN];
u16 auth_alg, auth_transaction, status_code;
struct sta_info *sta;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 6)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->auth_data || ifmgd->auth_data->done)
- return RX_MGMT_NONE;
+ return;
memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
if (!ether_addr_equal(bssid, mgmt->bssid))
- return RX_MGMT_NONE;
+ return;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
@@ -2330,14 +2291,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
auth_transaction,
ifmgd->auth_data->expected_transaction);
- return RX_MGMT_NONE;
+ return;
}
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied authentication (status %d)\n",
mgmt->sa, status_code);
ieee80211_destroy_auth_data(sdata, false);
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
}
switch (ifmgd->auth_data->algorithm) {
@@ -2350,20 +2312,20 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
if (ifmgd->auth_data->expected_transaction != 4) {
ieee80211_auth_challenge(sdata, mgmt, len);
/* need another frame */
- return RX_MGMT_NONE;
+ return;
}
break;
default:
WARN_ONCE(1, "invalid auth alg %d",
ifmgd->auth_data->algorithm);
- return RX_MGMT_NONE;
+ return;
}
sdata_info(sdata, "authenticated\n");
ifmgd->auth_data->done = true;
ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
ifmgd->auth_data->expected_transaction != 2) {
@@ -2371,7 +2333,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
* Report auth frame to user space for processing since another
* round of Authentication frames is still needed.
*/
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
}
/* move station state to auth */
@@ -2387,30 +2350,29 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
}
mutex_unlock(&sdata->local->sta_mtx);
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
out_err:
mutex_unlock(&sdata->local->sta_mtx);
/* ignore frame -- wait for timeout */
- return RX_MGMT_NONE;
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
const u8 *bssid = NULL;
u16 reason_code;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 2)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
bssid = ifmgd->associated->bssid;
@@ -2421,25 +2383,24 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- return RX_MGMT_CFG80211_DEAUTH;
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len);
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u16 reason_code;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 2)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -2448,7 +2409,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- return RX_MGMT_CFG80211_DISASSOC;
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len);
}
static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
@@ -2498,7 +2459,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if (!assoc) {
sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
@@ -2679,10 +2640,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
return true;
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len,
- struct cfg80211_bss **bss)
+static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt,
+ size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
@@ -2690,13 +2650,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems elems;
u8 *pos;
bool reassoc;
+ struct cfg80211_bss *bss;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (!assoc_data)
- return RX_MGMT_NONE;
+ return;
if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))
- return RX_MGMT_NONE;
+ return;
/*
* AssocResp and ReassocResp have identical structure, so process both
@@ -2704,7 +2665,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
*/
if (len < 24 + 6)
- return RX_MGMT_NONE;
+ return;
reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
@@ -2731,22 +2692,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
assoc_data->timeout_started = true;
if (ms > IEEE80211_ASSOC_TIMEOUT)
- run_again(ifmgd, assoc_data->timeout);
- return RX_MGMT_NONE;
+ run_again(sdata, assoc_data->timeout);
+ return;
}
- *bss = assoc_data->bss;
+ bss = assoc_data->bss;
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied association (code=%d)\n",
mgmt->sa, status_code);
ieee80211_destroy_assoc_data(sdata, false);
} else {
- if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
+ if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
/* oops -- internal error -- send timeout for now */
ieee80211_destroy_assoc_data(sdata, false);
- cfg80211_put_bss(sdata->local->hw.wiphy, *bss);
- return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
+ cfg80211_put_bss(sdata->local->hw.wiphy, bss);
+ cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
+ return;
}
sdata_info(sdata, "associated\n");
@@ -2758,7 +2720,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_destroy_assoc_data(sdata, true);
}
- return RX_MGMT_CFG80211_RX_ASSOC;
+ cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len);
}
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2772,7 +2734,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel;
bool need_ps = false;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if ((sdata->u.mgd.associated &&
ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
@@ -2831,7 +2793,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd = &sdata->u.mgd;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
return; /* ignore ProbeResp to foreign address */
@@ -2856,7 +2818,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data->tries = 0;
ifmgd->auth_data->timeout = jiffies;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
}
}
@@ -2881,10 +2843,9 @@ static const u64 care_about_ies =
(1ULL << WLAN_EID_HT_CAPABILITY) |
(1ULL << WLAN_EID_HT_OPERATION);
-static enum rx_mgmt_action
-ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len,
- u8 *deauth_buf, struct ieee80211_rx_status *rx_status)
+static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ struct ieee80211_rx_status *rx_status)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
@@ -2899,24 +2860,25 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
u8 erp_value = 0;
u32 ncrc;
u8 *bssid;
+ u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
/* Process beacon from the current BSS */
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
if (baselen > len)
- return RX_MGMT_NONE;
+ return;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
- return RX_MGMT_NONE;
+ return;
}
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
rcu_read_unlock();
- return RX_MGMT_NONE;
+ return;
}
chan = chanctx_conf->def.chan;
rcu_read_unlock();
@@ -2943,13 +2905,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
/* continue assoc process */
ifmgd->assoc_data->timeout = jiffies;
ifmgd->assoc_data->timeout_started = true;
- run_again(ifmgd, ifmgd->assoc_data->timeout);
- return RX_MGMT_NONE;
+ run_again(sdata, ifmgd->assoc_data->timeout);
+ return;
}
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
bssid = ifmgd->associated->bssid;
/* Track average RSSI from the Beacon frames of the current AP */
@@ -3095,7 +3057,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
- return RX_MGMT_NONE;
+ return;
ifmgd->beacon_crc = ncrc;
ifmgd->beacon_crc_valid = true;
@@ -3151,7 +3113,9 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DEAUTH_LEAVING,
true, deauth_buf);
- return RX_MGMT_CFG80211_TX_DEAUTH;
+ cfg80211_send_deauth(sdata->dev, deauth_buf,
+ sizeof(deauth_buf));
+ return;
}
if (sta && elems.opmode_notif)
@@ -3168,19 +3132,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
elems.pwr_constr_elem);
ieee80211_bss_info_change_notify(sdata, changed);
-
- return RX_MGMT_NONE;
}
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
- struct cfg80211_bss *bss = NULL;
- enum rx_mgmt_action rma = RX_MGMT_NONE;
- u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
u16 fc;
struct ieee802_11_elems elems;
int ies_len;
@@ -3189,28 +3147,27 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BEACON:
- rma = ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
- deauth_buf, rx_status);
+ ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len, rx_status);
break;
case IEEE80211_STYPE_PROBE_RESP:
ieee80211_rx_mgmt_probe_resp(sdata, skb);
break;
case IEEE80211_STYPE_AUTH:
- rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_DEAUTH:
- rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_DISASSOC:
- rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
- rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
+ ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ACTION:
if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
@@ -3256,34 +3213,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}
break;
}
- mutex_unlock(&ifmgd->mtx);
-
- switch (rma) {
- case RX_MGMT_NONE:
- /* no action */
- break;
- case RX_MGMT_CFG80211_DEAUTH:
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_DISASSOC:
- cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_RX_AUTH:
- cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_RX_ASSOC:
- cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_ASSOC_TIMEOUT:
- cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
- break;
- case RX_MGMT_CFG80211_TX_DEAUTH:
- cfg80211_send_deauth(sdata->dev, deauth_buf,
- sizeof(deauth_buf));
- break;
- default:
- WARN(1, "unexpected: %d", rma);
- }
+ sdata_unlock(sdata);
}
static void ieee80211_sta_timer(unsigned long data)
@@ -3297,20 +3227,12 @@ static void ieee80211_sta_timer(unsigned long data)
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 reason, bool tx)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
tx, frame_buf);
- mutex_unlock(&ifmgd->mtx);
- /*
- * must be outside lock due to cfg80211,
- * but that's not a problem.
- */
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
-
- mutex_lock(&ifmgd->mtx);
}
static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3320,7 +3242,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
u32 tx_flags = 0;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (WARN_ON_ONCE(!auth_data))
return -EINVAL;
@@ -3393,7 +3315,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, auth_data->timeout);
+ run_again(sdata, auth_data->timeout);
} else {
auth_data->timeout_started = false;
}
@@ -3406,7 +3328,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
struct ieee80211_local *local = sdata->local;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
assoc_data->tries++;
if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
@@ -3430,7 +3352,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
assoc_data->timeout_started = true;
- run_again(&sdata->u.mgd, assoc_data->timeout);
+ run_again(sdata, assoc_data->timeout);
} else {
assoc_data->timeout_started = false;
}
@@ -3455,7 +3377,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (ifmgd->status_received) {
__le16 fc = ifmgd->status_fc;
@@ -3467,7 +3389,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (status_acked) {
ifmgd->auth_data->timeout =
jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
} else {
ifmgd->auth_data->timeout = jiffies - 1;
}
@@ -3478,7 +3400,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (status_acked) {
ifmgd->assoc_data->timeout =
jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;
- run_again(ifmgd, ifmgd->assoc_data->timeout);
+ run_again(sdata, ifmgd->assoc_data->timeout);
} else {
ifmgd->assoc_data->timeout = jiffies - 1;
}
@@ -3501,12 +3423,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
cfg80211_send_auth_timeout(sdata->dev, bssid);
- mutex_lock(&ifmgd->mtx);
}
} else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
time_after(jiffies, ifmgd->assoc_data->timeout)) {
@@ -3519,12 +3439,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_destroy_assoc_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
cfg80211_send_assoc_timeout(sdata->dev, bssid);
- mutex_lock(&ifmgd->mtx);
}
} else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
- run_again(ifmgd, ifmgd->assoc_data->timeout);
+ run_again(sdata, ifmgd->assoc_data->timeout);
if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL) &&
@@ -3558,7 +3476,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
false);
}
} else if (time_is_after_jiffies(ifmgd->probe_timeout))
- run_again(ifmgd, ifmgd->probe_timeout);
+ run_again(sdata, ifmgd->probe_timeout);
else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
mlme_dbg(sdata,
"Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
@@ -3587,7 +3505,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
}
}
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -3648,9 +3566,9 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
@@ -3661,10 +3579,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
ifmgd->associated->bssid,
WLAN_REASON_UNSPECIFIED,
true);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
#endif
@@ -3696,8 +3614,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
ifmgd->p2p_noa_index = -1;
- mutex_init(&ifmgd->mtx);
-
if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
else
@@ -4053,8 +3969,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* try to authenticate/probe */
- mutex_lock(&ifmgd->mtx);
-
if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
ifmgd->assoc_data) {
err = -EBUSY;
@@ -4084,8 +3998,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* hold our own reference */
cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
- err = 0;
- goto out_unlock;
+ return 0;
err_clear:
memset(ifmgd->bssid, 0, ETH_ALEN);
@@ -4093,9 +4006,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data = NULL;
err_free:
kfree(auth_data);
- out_unlock:
- mutex_unlock(&ifmgd->mtx);
-
return err;
}
@@ -4126,8 +4036,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
assoc_data->ssid_len = ssidie[1];
rcu_read_unlock();
- mutex_lock(&ifmgd->mtx);
-
if (ifmgd->associated)
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
@@ -4322,7 +4230,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
rcu_read_unlock();
- run_again(ifmgd, assoc_data->timeout);
+ run_again(sdata, assoc_data->timeout);
if (bss->corrupt_data) {
char *corrupt_type = "data";
@@ -4338,17 +4246,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
corrupt_type);
}
- err = 0;
- goto out;
+ return 0;
err_clear:
memset(ifmgd->bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
ifmgd->assoc_data = NULL;
err_free:
kfree(assoc_data);
- out:
- mutex_unlock(&ifmgd->mtx);
-
return err;
}
@@ -4360,8 +4264,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
bool tx = !req->local_state_change;
bool sent_frame = false;
- mutex_lock(&ifmgd->mtx);
-
sdata_info(sdata,
"deauthenticating from %pM by local choice (reason=%d)\n",
req->bssid, req->reason_code);
@@ -4373,7 +4275,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
req->reason_code, tx,
frame_buf);
ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
sent_frame = tx;
goto out;
@@ -4385,12 +4286,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
req->reason_code, tx, frame_buf);
sent_frame = tx;
}
- mutex_unlock(&ifmgd->mtx);
out:
if (sent_frame)
- __cfg80211_send_deauth(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
+ cfg80211_send_deauth(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
return 0;
}
@@ -4402,18 +4302,14 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
u8 bssid[ETH_ALEN];
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- mutex_lock(&ifmgd->mtx);
-
/*
* cfg80211 should catch this ... but it's racy since
* we can receive a disassoc frame, process it, hand it
* to cfg80211 while that's in a locked section already
* trying to tell us that the user wants to disconnect.
*/
- if (ifmgd->associated != req->bss) {
- mutex_unlock(&ifmgd->mtx);
+ if (ifmgd->associated != req->bss)
return -ENOLINK;
- }
sdata_info(sdata,
"disassociating from %pM by local choice (reason=%d)\n",
@@ -4423,10 +4319,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
req->reason_code, !req->local_state_change,
frame_buf);
- mutex_unlock(&ifmgd->mtx);
- __cfg80211_send_disassoc(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
+ cfg80211_send_disassoc(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
return 0;
}
@@ -4446,13 +4341,13 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->csa_connection_drop_work);
cancel_work_sync(&ifmgd->chswitch_work);
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false);
if (ifmgd->auth_data)
ieee80211_destroy_auth_data(sdata, false);
del_timer_sync(&ifmgd->timer);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 27e0715..16366b3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1607,9 +1607,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (sdata->u.mgd.dtim_period)
changed |= BSS_CHANGED_DTIM_PERIOD;
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
ieee80211_bss_info_change_notify(sdata, changed);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
break;
case NL80211_IFTYPE_ADHOC:
changed |= BSS_CHANGED_IBSS;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 2f9d20c..06e982d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_rx_auth(dev);
- wdev_lock(wdev);
nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
cfg80211_sme_rx_auth(dev, buf, len);
-
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);
@@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
trace_cfg80211_send_rx_assoc(dev, bss);
- wdev_lock(wdev);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
cfg80211_sme_failed_reassoc(wdev)) {
cfg80211_put_bss(wiphy, bss);
- goto out;
+ return;
}
nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
@@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* sme will schedule work that does it later.
*/
cfg80211_put_bss(wiphy, bss);
- goto out;
+ return;
}
if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
@@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
status_code,
status_code == WLAN_STATUS_SUCCESS, bss);
- out:
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
-void __cfg80211_send_deauth(struct net_device *dev,
- const u8 *buf, size_t len)
+void cfg80211_send_deauth(struct net_device *dev,
+ const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
const u8 *bssid = mgmt->bssid;
bool was_current = false;
- trace___cfg80211_send_deauth(dev);
+ trace_cfg80211_send_deauth(dev);
ASSERT_WDEV_LOCK(wdev);
if (wdev->current_bss &&
@@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev,
false, NULL);
}
}
-EXPORT_SYMBOL(__cfg80211_send_deauth);
-
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
- wdev_lock(wdev);
- __cfg80211_send_deauth(dev, buf, len);
- wdev_unlock(wdev);
-}
EXPORT_SYMBOL(cfg80211_send_deauth);
-void __cfg80211_send_disassoc(struct net_device *dev,
- const u8 *buf, size_t len)
+void cfg80211_send_disassoc(struct net_device *dev,
+ const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev,
u16 reason_code;
bool from_ap;
- trace___cfg80211_send_disassoc(dev);
+ trace_cfg80211_send_disassoc(dev);
ASSERT_WDEV_LOCK(wdev);
nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
@@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev,
from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
}
-EXPORT_SYMBOL(__cfg80211_send_disassoc);
-
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
- wdev_lock(wdev);
- __cfg80211_send_disassoc(dev, buf, len);
- wdev_unlock(wdev);
-}
EXPORT_SYMBOL(cfg80211_send_disassoc);
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
@@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_auth_timeout(dev, addr);
- wdev_lock(wdev);
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);
-
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
@@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_assoc_timeout(dev, addr);
- wdev_lock(wdev);
nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);
-
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 5755bc1..23fafea 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1911,12 +1911,12 @@ TRACE_EVENT(cfg80211_send_rx_assoc,
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
);
-DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth,
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_deauth,
TP_PROTO(struct net_device *netdev),
TP_ARGS(netdev)
);
-DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc,
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_disassoc,
TP_PROTO(struct net_device *netdev),
TP_ARGS(netdev)
);
--
1.8.0
^ permalink raw reply related
* [RFC v2 3/4] cfg80211: vastly simplify locking
From: Johannes Berg @ 2013-05-10 13:43 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368193436-26618-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Virtually all code paths in cfg80211 already (need to) hold
the RTNL. As such, there's little point in having another
four mutexes for various parts of the code, they just cause
lock ordering issues (and much of the time, the RTNL and a
few of the others need thus be held.)
Simplify all this by getting rid of the extra four mutexes
and just use the RTNL throughout. Only a few code changes
were needed to do this and we can get rid of a work struct
for bonus points.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/cfg80211.h | 5 +-
net/wireless/core.c | 169 +++++++++---------------------------------
net/wireless/core.h | 32 +-------
net/wireless/debugfs.c | 4 +-
net/wireless/ibss.c | 10 +--
net/wireless/mesh.c | 2 -
net/wireless/mlme.c | 12 +--
net/wireless/nl80211.c | 178 +++++++++------------------------------------
net/wireless/reg.c | 36 +++------
net/wireless/scan.c | 42 +++++------
net/wireless/sme.c | 26 +------
net/wireless/util.c | 11 ---
net/wireless/wext-compat.c | 22 +-----
net/wireless/wext-sme.c | 18 -----
14 files changed, 120 insertions(+), 447 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 26e9113..085e5f7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1255,6 +1255,7 @@ struct cfg80211_ssid {
* @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
+ * @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/
struct cfg80211_scan_request {
@@ -1272,7 +1273,7 @@ struct cfg80211_scan_request {
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
- bool aborted;
+ bool aborted, notified;
bool no_cck;
/* keep last */
@@ -2872,8 +2873,6 @@ struct wireless_dev {
struct mutex mtx;
- struct work_struct cleanup_work;
-
bool use_4addr, p2p_started;
u8 address[ETH_ALEN] __aligned(sizeof(u16));
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 875d79a..3837326 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -36,12 +36,10 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support");
MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
-/* RCU-protected (and cfg80211_mutex for writers) */
+/* RCU-protected (and RTNL for writers) */
LIST_HEAD(cfg80211_rdev_list);
int cfg80211_rdev_list_generation;
-DEFINE_MUTEX(cfg80211_mutex);
-
/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;
@@ -53,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
"Disable 40MHz support in the 2.4GHz band");
-/* requires cfg80211_mutex to be held! */
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
{
struct cfg80211_registered_device *result = NULL, *rdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (rdev->wiphy_idx == wiphy_idx) {
@@ -77,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy)
return rdev->wiphy_idx;
}
-/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
{
struct cfg80211_registered_device *rdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
if (!rdev)
@@ -90,14 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
{
struct cfg80211_registered_device *rdev2;
int wiphy_idx, taken = -1, result, digits;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
/* prohibit calling the thing phy%d when %d is not its number */
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
@@ -195,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev)
{
- lockdep_assert_held(&rdev->devlist_mtx);
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
return;
@@ -235,8 +229,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
rtnl_lock();
- /* read-only iteration need not hold the devlist_mtx */
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->netdev) {
dev_close(wdev->netdev);
@@ -245,12 +237,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
/* otherwise, check iftype */
switch (wdev->iftype) {
case NL80211_IFTYPE_P2P_DEVICE:
- /* but this requires it */
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
break;
default:
break;
@@ -278,10 +265,7 @@ static void cfg80211_event_work(struct work_struct *work)
event_work);
rtnl_lock();
- cfg80211_lock_rdev(rdev);
-
cfg80211_process_rdev_events(rdev);
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -323,9 +307,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
/* give it a proper name */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
- mutex_init(&rdev->mtx);
- mutex_init(&rdev->devlist_mtx);
- mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->wdev_list);
INIT_LIST_HEAD(&rdev->beacon_registrations);
spin_lock_init(&rdev->beacon_registrations_lock);
@@ -573,11 +554,11 @@ int wiphy_register(struct wiphy *wiphy)
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
res = device_add(&rdev->wiphy.dev);
if (res) {
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
return res;
}
@@ -606,23 +587,19 @@ int wiphy_register(struct wiphy *wiphy)
}
cfg80211_debugfs_rdev_add(rdev);
- mutex_unlock(&cfg80211_mutex);
- /*
- * due to a locking dependency this has to be outside of the
- * cfg80211_mutex lock
- */
res = rfkill_register(rdev->rfkill);
if (res)
goto out_rm_dev;
- rtnl_lock();
rdev->wiphy.registered = true;
- rtnl_unlock();
- return 0;
+ res = 0;
+ goto out;
out_rm_dev:
device_del(&rdev->wiphy.dev);
+out:
+ rtnl_unlock();
return res;
}
EXPORT_SYMBOL(wiphy_register);
@@ -650,25 +627,19 @@ void wiphy_unregister(struct wiphy *wiphy)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- rtnl_lock();
- rdev->wiphy.registered = false;
- rtnl_unlock();
-
- rfkill_unregister(rdev->rfkill);
-
- /* protect the device list */
- mutex_lock(&cfg80211_mutex);
-
wait_event(rdev->dev_wait, ({
int __count;
- mutex_lock(&rdev->devlist_mtx);
+ rtnl_lock();
__count = rdev->opencount;
- mutex_unlock(&rdev->devlist_mtx);
+ rtnl_unlock();
__count == 0; }));
- mutex_lock(&rdev->devlist_mtx);
+ rtnl_lock();
+ rdev->wiphy.registered = false;
+
+ rfkill_unregister(rdev->rfkill);
+
BUG_ON(!list_empty(&rdev->wdev_list));
- mutex_unlock(&rdev->devlist_mtx);
/*
* First remove the hardware from everywhere, this makes
@@ -679,20 +650,6 @@ void wiphy_unregister(struct wiphy *wiphy)
synchronize_rcu();
/*
- * Try to grab rdev->mtx. If a command is still in progress,
- * hopefully the driver will refuse it since it's tearing
- * down the device already. We wait for this command to complete
- * before unlinking the item from the list.
- * Note: as codified by the BUG_ON above we cannot get here if
- * a virtual interface is still present. Hence, we can only get
- * to lock contention here if userspace issues a command that
- * identified the hardware by wiphy index.
- */
- cfg80211_lock_rdev(rdev);
- /* nothing */
- cfg80211_unlock_rdev(rdev);
-
- /*
* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint
*/
@@ -701,7 +658,7 @@ void wiphy_unregister(struct wiphy *wiphy)
cfg80211_rdev_list_generation++;
device_del(&rdev->wiphy.dev);
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
flush_work(&rdev->scan_done_wk);
cancel_work_sync(&rdev->conn_work);
@@ -719,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
struct cfg80211_internal_bss *scan, *tmp;
struct cfg80211_beacon_registration *reg, *treg;
rfkill_destroy(rdev->rfkill);
- mutex_destroy(&rdev->mtx);
- mutex_destroy(&rdev->devlist_mtx);
- mutex_destroy(&rdev->sched_scan_mtx);
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
list_del(®->list);
kfree(reg);
@@ -746,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
}
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
-static void wdev_cleanup_work(struct work_struct *work)
-{
- struct wireless_dev *wdev;
- struct cfg80211_registered_device *rdev;
-
- wdev = container_of(work, struct wireless_dev, cleanup_work);
- rdev = wiphy_to_dev(wdev->wiphy);
-
- mutex_lock(&rdev->sched_scan_mtx);
-
- if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
- rdev->scan_req->aborted = true;
- ___cfg80211_scan_done(rdev, true);
- }
-
- if (WARN_ON(rdev->sched_scan_req &&
- rdev->sched_scan_req->dev == wdev->netdev)) {
- __cfg80211_stop_sched_scan(rdev, false);
- }
-
- mutex_unlock(&rdev->sched_scan_mtx);
-
- mutex_lock(&rdev->devlist_mtx);
- rdev->opencount--;
- mutex_unlock(&rdev->devlist_mtx);
- wake_up(&rdev->dev_wait);
-
- dev_put(wdev->netdev);
-}
-
void cfg80211_unregister_wdev(struct wireless_dev *wdev)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
@@ -785,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
if (WARN_ON(wdev->netdev))
return;
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
list_del_rcu(&wdev->list);
rdev->devlist_generation++;
@@ -798,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
WARN_ON_ONCE(1);
break;
}
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
}
EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -818,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
}
void cfg80211_leave(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev)
+ struct wireless_dev *wdev)
{
struct net_device *dev = wdev->netdev;
@@ -828,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
- mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
#ifdef CONFIG_CFG80211_WEXT
@@ -884,13 +802,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* are added with nl80211.
*/
mutex_init(&wdev->mtx);
- INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
INIT_LIST_HEAD(&wdev->event_list);
spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
- mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
@@ -903,7 +819,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
}
wdev->netdev = dev;
wdev->sme_state = CFG80211_SME_IDLE;
- mutex_unlock(&rdev->devlist_mtx);
#ifdef CONFIG_CFG80211_WEXT
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
@@ -929,26 +844,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_DOWN:
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
- dev_hold(dev);
- queue_work(cfg80211_wq, &wdev->cleanup_work);
+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+ if (WARN_ON(!rdev->scan_req->notified))
+ rdev->scan_req->aborted = true;
+ ___cfg80211_scan_done(rdev, true);
+ }
+
+ if (WARN_ON(rdev->sched_scan_req &&
+ rdev->sched_scan_req->dev == wdev->netdev)) {
+ __cfg80211_stop_sched_scan(rdev, false);
+ }
+
+ rdev->opencount--;
+ wake_up(&rdev->dev_wait);
break;
case NETDEV_UP:
- /*
- * If we have a really quick DOWN/UP succession we may
- * have this work still pending ... cancel it and see
- * if it was pending, in which case we need to account
- * for some of the work it would have done.
- */
- if (cancel_work_sync(&wdev->cleanup_work)) {
- mutex_lock(&rdev->devlist_mtx);
- rdev->opencount--;
- mutex_unlock(&rdev->devlist_mtx);
- dev_put(dev);
- }
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
switch (wdev->iftype) {
#ifdef CONFIG_CFG80211_WEXT
@@ -980,10 +891,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
}
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
rdev->opencount++;
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
/*
* Configure power management to the driver here so that its
@@ -1000,12 +908,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_UNREGISTER:
/*
- * NB: cannot take rdev->mtx here because this may be
- * called within code protected by it when interfaces
- * are removed with nl80211.
- */
- mutex_lock(&rdev->devlist_mtx);
- /*
* It is possible to get NETDEV_UNREGISTER
* multiple times. To detect that, check
* that the interface is still on the list
@@ -1021,7 +923,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
kfree(wdev->wext.keys);
#endif
}
- mutex_unlock(&rdev->devlist_mtx);
/*
* synchronise (so that we won't find this netdev
* from other code any more) and then clear the list
@@ -1041,9 +942,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL);
- mutex_lock(&rdev->devlist_mtx);
ret = cfg80211_can_add_interface(rdev, wdev->iftype);
- mutex_unlock(&rdev->devlist_mtx);
if (ret)
return notifier_from_errno(ret);
break;
@@ -1061,12 +960,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
struct cfg80211_registered_device *rdev;
rtnl_lock();
- mutex_lock(&cfg80211_mutex);
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (net_eq(wiphy_net(&rdev->wiphy), net))
WARN_ON(cfg80211_switch_netns(rdev, &init_net));
}
- mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 95b2907..d21a0fc 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -5,7 +5,6 @@
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
-#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/rbtree.h>
@@ -23,11 +22,6 @@
struct cfg80211_registered_device {
const struct cfg80211_ops *ops;
struct list_head list;
- /* we hold this mutex during any call so that
- * we cannot do multiple calls at once, and also
- * to avoid the deregister call to proceed while
- * any call is in progress */
- struct mutex mtx;
/* rfkill support */
struct rfkill_ops rfkill_ops;
@@ -49,9 +43,7 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */
int wiphy_idx;
- /* associated wireless interfaces */
- struct mutex devlist_mtx;
- /* protected by devlist_mtx or RCU */
+ /* associated wireless interfaces, protected by rtnl or RCU */
struct list_head wdev_list;
int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */
@@ -75,8 +67,6 @@ struct cfg80211_registered_device {
struct work_struct scan_done_wk;
struct work_struct sched_scan_results_wk;
- struct mutex sched_scan_mtx;
-
#ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info;
#endif
@@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
}
extern struct workqueue_struct *cfg80211_wq;
-extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_rdev_list;
extern int cfg80211_rdev_list_generation;
-static inline void assert_cfg80211_lock(void)
-{
- lockdep_assert_held(&cfg80211_mutex);
-}
-
struct cfg80211_internal_bss {
struct list_head list;
struct list_head hidden_list;
@@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy);
-/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net);
-static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
-{
- mutex_lock(&rdev->mtx);
-}
-
-static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
-{
- BUG_ON(IS_ERR(rdev) || !rdev);
- mutex_unlock(&rdev->mtx);
-}
-
static inline void wdev_lock(struct wireless_dev *wdev)
__acquires(wdev)
{
@@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
mutex_unlock(&wdev->mtx);
}
-#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
+#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 920cabe..90d0500 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
if (!buf)
return -ENOMEM;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band];
@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
buf, buf_size, offset);
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index d80e471..5449c5a 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(wdev);
err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
wdev->wext.ibss.channel_fixed = false;
}
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
memcpy(wdev->wext.ibss.ssid, ssid, len);
wdev->wext.ibss.ssid_len = len;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
} else
wdev->wext.ibss.bssid = NULL;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 0bb93f3..6c216ad 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -185,11 +185,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 0c7b7dd..2f9d20c 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -314,14 +314,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
{
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
key, key_len, key_idx,
sae_data, sae_data_len);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -425,12 +425,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
ssid, ssid_len, req);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -848,7 +848,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
dfs_update_channels_wk);
wiphy = &rdev->wiphy;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
sband = wiphy->bands[bandid];
if (!sband)
@@ -881,7 +881,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
check_again = true;
}
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
/* reschedule if there are other channels waiting to be cleared again */
if (check_again)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9cdcd9e..74cef32 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
int wiphy_idx = -1;
int ifidx = -1;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
if (!have_ifidx && !have_wdev_id)
return ERR_PTR(-EINVAL);
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
continue;
- mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (have_ifidx && wdev->netdev &&
wdev->netdev->ifindex == ifidx) {
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
break;
}
}
- mutex_unlock(&rdev->devlist_mtx);
if (result)
break;
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
struct cfg80211_registered_device *rdev = NULL, *tmp;
struct net_device *netdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
if (!attrs[NL80211_ATTR_WIPHY] &&
!attrs[NL80211_ATTR_IFINDEX] &&
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
if (tmp) {
/* make sure wdev exists */
- mutex_lock(&tmp->devlist_mtx);
list_for_each_entry(wdev, &tmp->wdev_list, list) {
if (wdev->identifier != (u32)wdev_id)
continue;
found = true;
break;
}
- mutex_unlock(&tmp->devlist_mtx);
if (!found)
tmp = NULL;
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
/*
* This function returns a pointer to the driver
* that the genl_info item that is passed refers to.
- * If successful, it returns non-NULL and also locks
- * the driver's mutex!
- *
- * This means that you need to call cfg80211_unlock_rdev()
- * before being allowed to acquire &cfg80211_mutex!
- *
- * This is necessary because we need to lock the global
- * mutex to get an item off the list safely, and then
- * we lock the rdev mutex so it doesn't go away under us.
- *
- * We don't want to keep cfg80211_mutex locked
- * for all the time in order to allow requests on
- * other interfaces to go through at the same time.
*
* The result of this can be a PTR_ERR and hence must
* be checked with IS_ERR() for errors.
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
static struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
-
- mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
-
- /* if it is not an error we grab the lock on
- * it to assure it won't be going away while
- * we operate on it */
- if (!IS_ERR(rdev))
- mutex_lock(&rdev->mtx);
-
- mutex_unlock(&cfg80211_mutex);
-
- return rdev;
+ return __cfg80211_rdev_from_attrs(netns, info->attrs);
}
/* policy for the attributes */
@@ -455,7 +425,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
int err;
rtnl_lock();
- mutex_lock(&cfg80211_mutex);
if (!cb->args[0]) {
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
@@ -484,14 +453,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
*rdev = wiphy_to_dev(wiphy);
*wdev = NULL;
- mutex_lock(&(*rdev)->devlist_mtx);
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
if (tmp->identifier == cb->args[1]) {
*wdev = tmp;
break;
}
}
- mutex_unlock(&(*rdev)->devlist_mtx);
if (!*wdev) {
err = -ENODEV;
@@ -499,19 +466,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
}
}
- cfg80211_lock_rdev(*rdev);
-
- mutex_unlock(&cfg80211_mutex);
return 0;
out_unlock:
- mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
return err;
}
static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
{
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -1567,7 +1529,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
struct nlattr **tb = nl80211_fam.attrbuf;
int res;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
tb, nl80211_fam.maxattr, nl80211_policy);
if (res == 0) {
@@ -1581,10 +1543,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
- if (!netdev) {
- mutex_unlock(&cfg80211_mutex);
+ if (!netdev)
return -ENODEV;
- }
if (netdev->ieee80211_ptr) {
dev = wiphy_to_dev(
netdev->ieee80211_ptr->wiphy);
@@ -1628,7 +1588,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
!skb->len &&
cb->min_dump_alloc < 4096) {
cb->min_dump_alloc = 4096;
- mutex_unlock(&cfg80211_mutex);
return 1;
}
idx--;
@@ -1637,7 +1596,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
} while (cb->args[1] > 0);
break;
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
cb->args[0] = idx;
@@ -1792,7 +1751,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
if (result)
return result;
- mutex_lock(&rdev->devlist_mtx);
switch (iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
@@ -1816,7 +1774,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
default:
result = -EINVAL;
}
- mutex_unlock(&rdev->devlist_mtx);
return result;
}
@@ -1865,6 +1822,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 frag_threshold = 0, rts_threshold = 0;
u8 coverage_class = 0;
+ ASSERT_RTNL();
+
/*
* Try to find the wiphy and netdev. Normally this
* function shouldn't need the netdev, but this is
@@ -1874,31 +1833,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
* also passed a netdev to set_wiphy, so that it is
* possible to let that go to the right netdev!
*/
- mutex_lock(&cfg80211_mutex);
if (info->attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(genl_info_net(info), ifindex);
- if (netdev && netdev->ieee80211_ptr) {
+ if (netdev && netdev->ieee80211_ptr)
rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
+ else
netdev = NULL;
}
if (!netdev) {
rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
info->attrs);
- if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
+ if (IS_ERR(rdev))
return PTR_ERR(rdev);
- }
wdev = NULL;
netdev = NULL;
result = 0;
-
- mutex_lock(&rdev->mtx);
} else
wdev = netdev->ieee80211_ptr;
@@ -1911,8 +1864,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = cfg80211_dev_rename(
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
- mutex_unlock(&cfg80211_mutex);
-
if (result)
goto bad_res;
@@ -2119,7 +2070,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
bad_res:
- mutex_unlock(&rdev->mtx);
if (netdev)
dev_put(netdev);
return result;
@@ -2217,7 +2167,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
continue;
@@ -2227,7 +2177,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
}
if_idx = 0;
- mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (if_idx < if_start) {
if_idx++;
@@ -2236,17 +2185,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev) < 0) {
- mutex_unlock(&rdev->devlist_mtx);
goto out;
}
if_idx++;
}
- mutex_unlock(&rdev->devlist_mtx);
wp_idx++;
}
out:
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
cb->args[0] = wp_idx;
cb->args[1] = if_idx;
@@ -2479,11 +2426,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
- mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
- mutex_unlock(&rdev->devlist_mtx);
break;
default:
break;
@@ -2992,8 +2937,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev;
bool ret = false;
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO)
@@ -3007,8 +2950,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
break;
}
- mutex_unlock(&rdev->devlist_mtx);
-
return ret;
}
@@ -3170,13 +3111,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.radar_required = true;
}
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
params.chandef.chan,
CHAN_MODE_SHARED,
radar_detect_width);
- mutex_unlock(&rdev->devlist_mtx);
-
if (err)
return err;
@@ -4899,18 +4837,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
void *hdr = NULL;
struct nlattr *nl_reg_rules;
unsigned int i;
- int err = -EINVAL;
-
- mutex_lock(&cfg80211_mutex);
if (!cfg80211_regdomain)
- goto out;
+ return -EINVAL;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOBUFS;
- goto out;
- }
+ if (!msg)
+ return -ENOBUFS;
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
NL80211_CMD_GET_REG);
@@ -4969,8 +4902,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
nla_nest_end(msg, nl_reg_rules);
genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
+ return genlmsg_reply(msg, info);
nla_put_failure_rcu:
rcu_read_unlock();
@@ -4978,10 +4910,7 @@ nla_put_failure:
genlmsg_cancel(msg, hdr);
put_failure:
nlmsg_free(msg);
- err = -EMSGSIZE;
-out:
- mutex_unlock(&cfg80211_mutex);
- return err;
+ return -EMSGSIZE;
}
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
@@ -5047,12 +4976,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
}
}
- mutex_lock(&cfg80211_mutex);
-
r = set_regdom(rd);
/* set_regdom took ownership */
rd = NULL;
- mutex_unlock(&cfg80211_mutex);
bad_reg:
kfree(rd);
@@ -5102,7 +5028,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->scan)
return -EOPNOTSUPP;
- mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) {
err = -EBUSY;
goto unlock;
@@ -5288,7 +5213,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
}
unlock:
- mutex_unlock(&rdev->sched_scan_mtx);
return err;
}
@@ -5360,8 +5284,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (ie_len > wiphy->max_sched_scan_ie_len)
return -EINVAL;
- mutex_lock(&rdev->sched_scan_mtx);
-
if (rdev->sched_scan_req) {
err = -EINPROGRESS;
goto out;
@@ -5529,7 +5451,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
out_free:
kfree(request);
out:
- mutex_unlock(&rdev->sched_scan_mtx);
return err;
}
@@ -5537,17 +5458,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- int err;
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
!rdev->ops->sched_scan_stop)
return -EOPNOTSUPP;
- mutex_lock(&rdev->sched_scan_mtx);
- err = __cfg80211_stop_sched_scan(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
-
- return err;
+ return __cfg80211_stop_sched_scan(rdev, false);
}
static int nl80211_start_radar_detection(struct sk_buff *skb,
@@ -5579,12 +5495,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (!rdev->ops->start_radar_detection)
return -EOPNOTSUPP;
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
chandef.chan, CHAN_MODE_SHARED,
BIT(chandef.width));
if (err)
- goto err_locked;
+ return err;
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
if (!err) {
@@ -5592,9 +5507,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
}
-err_locked:
- mutex_unlock(&rdev->devlist_mtx);
-
return err;
}
@@ -6457,6 +6369,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
void *data = NULL;
int data_len = 0;
+ rtnl_lock();
+
if (cb->args[0]) {
/*
* 0 is a valid index, but not valid for args[0],
@@ -6468,18 +6382,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
nl80211_fam.attrbuf, nl80211_fam.maxattr,
nl80211_policy);
if (err)
- return err;
+ goto out_err;
- mutex_lock(&cfg80211_mutex);
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
nl80211_fam.attrbuf);
if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
- return PTR_ERR(rdev);
+ err = PTR_ERR(rdev);
+ goto out_err;
}
phy_idx = rdev->wiphy_idx;
rdev = NULL;
- mutex_unlock(&cfg80211_mutex);
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
cb->args[1] =
@@ -6491,14 +6403,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
data_len = nla_len((void *)cb->args[1]);
}
- mutex_lock(&cfg80211_mutex);
rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
if (!rdev) {
- mutex_unlock(&cfg80211_mutex);
- return -ENOENT;
+ err = -ENOENT;
+ goto out_err;
}
- cfg80211_lock_rdev(rdev);
- mutex_unlock(&cfg80211_mutex);
if (!rdev->ops->testmode_dump) {
err = -EOPNOTSUPP;
@@ -6539,7 +6448,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
/* see above */
cb->args[0] = phy_idx + 1;
out_err:
- cfg80211_unlock_rdev(rdev);
+ rtnl_unlock();
return err;
}
@@ -8172,9 +8081,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (wdev->p2p_started)
return 0;
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_add_interface(rdev, wdev->iftype);
- mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -8183,9 +8090,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
return err;
wdev->p2p_started = true;
- mutex_lock(&rdev->devlist_mtx);
rdev->opencount++;
- mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8201,11 +8106,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->stop_p2p_device)
return -EOPNOTSUPP;
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8348,11 +8249,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
info->user_ptr[0] = rdev;
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
info->attrs);
if (IS_ERR(wdev)) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return PTR_ERR(wdev);
@@ -8363,7 +8264,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
if (!dev) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -EINVAL;
@@ -8377,7 +8277,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
if (dev) {
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
!netif_running(dev)) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
@@ -8386,17 +8285,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
dev_hold(dev);
} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
if (!wdev->p2p_started) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
}
}
- cfg80211_lock_rdev(rdev);
-
- mutex_unlock(&cfg80211_mutex);
-
info->user_ptr[0] = rdev;
}
@@ -8406,8 +8300,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
- if (info->user_ptr[0])
- cfg80211_unlock_rdev(info->user_ptr[0]);
if (info->user_ptr[1]) {
if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
struct wireless_dev *wdev = info->user_ptr[1];
@@ -8429,7 +8321,8 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_wiphy,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_WIPHY,
@@ -8444,7 +8337,8 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_interface,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WDEV,
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_INTERFACE,
@@ -8603,6 +8497,7 @@ static struct genl_ops nl80211_ops[] = {
.cmd = NL80211_CMD_GET_REG,
.doit = nl80211_get_reg,
.policy = nl80211_policy,
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
/* can be retrieved by unprivileged users */
},
{
@@ -8610,6 +8505,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_reg,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_REQ_SET_REG,
@@ -9065,8 +8961,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
struct nlattr *nest;
int i;
- lockdep_assert_held(&rdev->sched_scan_mtx);
-
if (WARN_ON(!req))
return 0;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e713051..5ceadbb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -387,7 +387,7 @@ static void reg_regdb_search(struct work_struct *work)
const struct ieee80211_regdomain *curdom, *regdom = NULL;
int i;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
mutex_lock(®_regdb_search_mutex);
while (!list_empty(®_regdb_search_list)) {
@@ -412,7 +412,7 @@ static void reg_regdb_search(struct work_struct *work)
if (!IS_ERR_OR_NULL(regdom))
set_regdom(regdom);
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
}
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
@@ -1235,7 +1235,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
struct cfg80211_registered_device *rdev;
struct wiphy *wiphy;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
wiphy = &rdev->wiphy;
@@ -1580,21 +1580,19 @@ static void reg_process_pending_hints(void)
{
struct regulatory_request *reg_request, *lr;
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
lr = get_last_request();
/* When last_request->processed becomes true this will be rescheduled */
if (lr && !lr->processed) {
REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
- goto out;
+ return;
}
spin_lock(®_requests_lock);
if (list_empty(®_requests_list)) {
spin_unlock(®_requests_lock);
- goto out;
+ return;
}
reg_request = list_first_entry(®_requests_list,
@@ -1605,10 +1603,6 @@ static void reg_process_pending_hints(void)
spin_unlock(®_requests_lock);
reg_process_hint(reg_request, reg_request->initiator);
-
-out:
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
}
/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1617,9 +1611,6 @@ static void reg_process_pending_beacon_hints(void)
struct cfg80211_registered_device *rdev;
struct reg_beacon *pending_beacon, *tmp;
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
-
/* This goes through the _pending_ beacon list */
spin_lock_bh(®_pending_beacons_lock);
@@ -1636,14 +1627,16 @@ static void reg_process_pending_beacon_hints(void)
}
spin_unlock_bh(®_pending_beacons_lock);
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
}
static void reg_todo(struct work_struct *work)
{
+ rtnl_lock();
+ mutex_lock(®_mutex);
reg_process_pending_hints();
reg_process_pending_beacon_hints();
+ mutex_unlock(®_mutex);
+ rtnl_unlock();
}
static void queue_regulatory_request(struct regulatory_request *request)
@@ -1727,10 +1720,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
}
EXPORT_SYMBOL(regulatory_hint);
-/*
- * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
- * therefore cannot iterate over the rdev list here.
- */
void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
const u8 *country_ie, u8 country_ie_len)
{
@@ -1762,7 +1751,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
/*
* We will run this only upon a successful connection on cfg80211.
* We leave conflict resolution to the workqueue, where can hold
- * cfg80211_mutex.
+ * the RTNL.
*/
if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
lr->wiphy_idx != WIPHY_IDX_INVALID)
@@ -1868,7 +1857,8 @@ static void restore_regulatory_settings(bool reset_user)
LIST_HEAD(tmp_reg_req_list);
struct cfg80211_registered_device *rdev;
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
mutex_lock(®_mutex);
reset_regdomains(true, &world_regdom);
@@ -1925,7 +1915,6 @@ static void restore_regulatory_settings(bool reset_user)
spin_unlock(®_requests_lock);
mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
REG_DBG_PRINT("Kicking the queue\n");
@@ -2307,7 +2296,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
mutex_unlock(®_mutex);
}
-/* Caller must hold cfg80211_mutex */
void wiphy_regulatory_deregister(struct wiphy *wiphy)
{
struct wiphy *request_wiphy = NULL;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2ce44a7..dd01b58 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
union iwreq_data wrqu;
#endif
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
request = rdev->scan_req;
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
scan_done_wk);
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
___cfg80211_scan_done(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
request->aborted = aborted;
+ request->notified = true;
queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
}
EXPORT_SYMBOL(cfg80211_scan_done);
@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
request = rdev->sched_scan_req;
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
/* we don't have sched_scan_req anymore if the scan is stopping */
if (request) {
@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
nl80211_send_sched_scan_results(rdev, request->dev);
}
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
void cfg80211_sched_scan_results(struct wiphy *wiphy)
@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
trace_cfg80211_sched_scan_stopped(wiphy);
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
__cfg80211_stop_sched_scan(rdev, true);
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
{
struct net_device *dev;
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
if (!rdev->sched_scan_req)
return -ENOENT;
@@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss);
static struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
dev = dev_get_by_index(net, ifindex);
if (!dev)
- goto out;
- if (dev->ieee80211_ptr) {
+ return ERR_PTR(-ENODEV);
+ if (dev->ieee80211_ptr)
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
+ else
rdev = ERR_PTR(-ENODEV);
dev_put(dev);
- out:
- mutex_unlock(&cfg80211_mutex);
return rdev;
}
@@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (IS_ERR(rdev))
return PTR_ERR(rdev);
- mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) {
err = -EBUSY;
goto out;
@@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
dev_hold(dev);
}
out:
- mutex_unlock(&rdev->sched_scan_mtx);
kfree(creq);
- cfg80211_unlock_rdev(rdev);
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
@@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
if (IS_ERR(rdev))
return PTR_ERR(rdev);
- if (rdev->scan_req) {
- res = -EAGAIN;
- goto out;
- }
+ if (rdev->scan_req)
+ return -EAGAIN;
res = ieee80211_scan_results(rdev, info, extra, data->length);
data->length = 0;
@@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
res = 0;
}
- out:
- cfg80211_unlock_rdev(rdev);
return res;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a9dc5c7..4a6d7af 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void)
struct wireless_dev *wdev;
bool is_all_idle = true;
- mutex_lock(&cfg80211_mutex);
-
/*
* All devices must be idle as otherwise if you are actively
* scanning some new beacon hints could be learned and would
* count as new regulatory hints.
*/
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
- cfg80211_lock_rdev(rdev);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE)
is_all_idle = false;
wdev_unlock(wdev);
}
- cfg80211_unlock_rdev(rdev);
}
- mutex_unlock(&cfg80211_mutex);
-
return is_all_idle;
}
static void disconnect_work(struct work_struct *work)
{
- if (!cfg80211_is_all_idle())
- return;
-
- regulatory_hint_disconnect();
+ rtnl_lock();
+ if (cfg80211_is_all_idle())
+ regulatory_hint_disconnect();
+ rtnl_unlock();
}
static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
@@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev);
ASSERT_WDEV_LOCK(wdev);
- lockdep_assert_held(&rdev->sched_scan_mtx);
if (rdev->scan_req)
return -EBUSY;
@@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work)
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
rtnl_lock();
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
@@ -253,9 +243,6 @@ void cfg80211_conn_work(struct work_struct *work)
wdev_unlock(wdev);
}
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -928,14 +915,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
{
int err;
- mutex_lock(&rdev->devlist_mtx);
- /* might request scan - scan_mtx -> wdev_mtx dependency */
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index bb52486..0be3f0d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -785,12 +785,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev);
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev);
-
- mutex_unlock(&rdev->devlist_mtx);
}
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
@@ -822,10 +818,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
return -EBUSY;
if (ntype != otype && netif_running(dev)) {
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
ntype);
- mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -1187,8 +1181,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
if (!beacon_int)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
@@ -1198,8 +1190,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
}
}
- mutex_unlock(&rdev->devlist_mtx);
-
return res;
}
@@ -1223,7 +1213,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
int i, j;
ASSERT_RTNL();
- lockdep_assert_held(&rdev->devlist_mtx);
if (WARN_ON(hweight32(radar_detect) > 1))
return -EINVAL;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index d997d0f..e7c6e86 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev;
struct vif_params vifparams;
enum nl80211_iftype type;
- int ret;
rdev = wiphy_to_dev(wdev->wiphy);
@@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams));
- cfg80211_lock_rdev(rdev);
- ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
- cfg80211_unlock_rdev(rdev);
-
- return ret;
+ return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
@@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
{
int err;
- /* devlist mutex needed for possible IBSS re-join */
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
remove, tx_key, idx, params);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
};
- int freq, err;
+ int freq;
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_monitor_channel(rdev, &chandef);
- mutex_unlock(&rdev->devlist_mtx);
- return err;
+ return cfg80211_set_monitor_channel(rdev, &chandef);
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
if (freq < 0)
@@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
- mutex_unlock(&rdev->devlist_mtx);
- return err;
+ return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
default:
return -EOPNOTSUPP;
}
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index e79cb5c..aeefd68 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
return -EINVAL;
}
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
@@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
if (len > 0 && ssid[len - 1] == '\0')
len--;
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
err = 0;
@@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
@@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
bssid = NULL;
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
--
1.8.0
^ permalink raw reply related
* [RFC v2 2/4] cfg80211: use atomic_t for wiphy counter
From: Johannes Berg @ 2013-05-10 13:43 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368193436-26618-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
There's no need to lock, we can just use an atomic_t.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/core.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 4e0b52f..875d79a 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -289,7 +289,7 @@ static void cfg80211_event_work(struct work_struct *work)
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
{
- static int wiphy_counter;
+ static atomic_t wiphy_counter = ATOMIC_INIT(0);
struct cfg80211_registered_device *rdev;
int alloc_size;
@@ -311,20 +311,15 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->ops = ops;
- mutex_lock(&cfg80211_mutex);
-
- rdev->wiphy_idx = wiphy_counter++;
+ rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
if (unlikely(rdev->wiphy_idx < 0)) {
- wiphy_counter--;
- mutex_unlock(&cfg80211_mutex);
/* ugh, wrapped! */
+ atomic_dec(&wiphy_counter);
kfree(rdev);
return NULL;
}
- mutex_unlock(&cfg80211_mutex);
-
/* give it a proper name */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
--
1.8.0
^ permalink raw reply related
* [RFC v2 1/4] cfg80211: move cfg80211_get_dev_from_ifindex under wext
From: Johannes Berg @ 2013-05-10 13:43 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
From: Johannes Berg <johannes.berg@intel.com>
The function is only used and needed by the wext code
for scanning, so move it there.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/core.c | 21 ---------------------
net/wireless/core.h | 4 ----
net/wireless/scan.c | 21 +++++++++++++++++++++
3 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 68f0c96..4e0b52f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -90,27 +90,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
-{
- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
- struct net_device *dev;
-
- mutex_lock(&cfg80211_mutex);
- dev = dev_get_by_index(net, ifindex);
- if (!dev)
- goto out;
- if (dev->ieee80211_ptr) {
- rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
- rdev = ERR_PTR(-ENODEV);
- dev_put(dev);
- out:
- mutex_unlock(&cfg80211_mutex);
- return rdev;
-}
-
/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index fd35dae..95b2907 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -164,10 +164,6 @@ int get_wiphy_idx(struct wiphy *wiphy);
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
-/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
-extern struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);
-
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index fd99ea4..2ce44a7 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1040,6 +1040,27 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
EXPORT_SYMBOL(cfg80211_unlink_bss);
#ifdef CONFIG_CFG80211_WEXT
+static struct cfg80211_registered_device *
+cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
+{
+ struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+ struct net_device *dev;
+
+ mutex_lock(&cfg80211_mutex);
+ dev = dev_get_by_index(net, ifindex);
+ if (!dev)
+ goto out;
+ if (dev->ieee80211_ptr) {
+ rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+ mutex_lock(&rdev->mtx);
+ } else
+ rdev = ERR_PTR(-ENODEV);
+ dev_put(dev);
+ out:
+ mutex_unlock(&cfg80211_mutex);
+ return rdev;
+}
+
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
--
1.8.0
^ permalink raw reply related
* [PATCH v2] ath9k: Fix crash on module unload
From: Sujith Manoharan @ 2013-05-10 13:11 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless, stable
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Make sure that any open relayfs files are closed before
unregistering with mac80211, otherwise this crash is seen:
[ 1331.097846] BUG: unable to handle kernel paging request at 6b6b6b8b
[ 1331.098170] IP: [<c063d0d6>] debugfs_remove+0x26/0x80
[ 1331.098170] *pdpt = 000000002f9aa001 *pde = 0000000000000000
[ 1331.098170] Oops: 0000 [#1] PREEMPT SMP
[ 1331.098170] Modules linked in: iptable_raw xt_CT nf_conntrack_ipv4 nf_defrag]
[ 1331.098170] Pid: 4794, comm: rmmod Tainted: G WC 3.9.1+ #5 To Be Fi.
[ 1331.098170] EIP: 0060:[<c063d0d6>] EFLAGS: 00010202 CPU: 0
[ 1331.098170] EIP is at debugfs_remove+0x26/0x80
[ 1331.098170] EAX: f2f3acd0 EBX: f2f3acd0 ECX: 00000006 EDX: f8622348
[ 1331.098170] ESI: 6b6b6b6b EDI: 00000001 EBP: ee251e14 ESP: ee251e0c
[ 1331.098170] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 1331.098170] CR0: 8005003b CR2: 6b6b6b8b CR3: 2e7b7000 CR4: 000007e0
[ 1331.098170] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 1331.098170] DR6: ffff0ff0 DR7: 00000400
[ 1331.098170] Process rmmod (pid: 4794, ti=ee250000 task=efaa2560 task.ti=ee25)
[ 1331.098170] Stack:
[ 1331.098170] f241e170 0000000a ee251e1c f861394d ee251e28 c04e3088 f241e170 4
[ 1331.098170] c04e30fe f45482b0 ee251e54 c04e3187 f25e86b0 ee251e54 f8618748 0
[ 1331.098170] 0000000a 00000001 ee251e68 f860065b f2509e20 f25085a0 f5b6e8a4 8
[ 1331.098170] Call Trace:
[ 1331.098170] [<f861394d>] remove_buf_file_handler+0xd/0x20 [ath9k]
[ 1331.098170] [<c04e3088>] relay_remove_buf+0x18/0x30
[ 1331.098170] [<c04e30fe>] relay_close_buf+0x2e/0x40
[ 1331.098170] [<c04e3187>] relay_close+0x77/0xf0
[ 1331.098170] [<f8618748>] ? dpd_exit+0x38/0x40 [ath9k]
[ 1331.098170] [<f860065b>] ath9k_deinit_softc+0x8b/0xa0 [ath9k]
[ 1331.098170] [<f86006b8>] ath9k_deinit_device+0x48/0x60 [ath9k]
[ 1331.098170] [<f86107f1>] ath_pci_remove+0x31/0x50 [ath9k]
[ 1331.098170] [<c06dbff8>] pci_device_remove+0x38/0xc0
[ 1331.098170] [<c079daa4>] __device_release_driver+0x64/0xc0
[ 1331.098170] [<c079db97>] driver_detach+0x97/0xa0
[ 1331.098170] [<c079cacc>] bus_remove_driver+0x6c/0xe0
[ 1331.098170] [<c079c197>] ? bus_put+0x17/0x20
[ 1331.098170] [<c079cae3>] ? bus_remove_driver+0x83/0xe0
[ 1331.098170] [<c079e709>] driver_unregister+0x49/0x80
[ 1331.098170] [<c06dc138>] pci_unregister_driver+0x18/0x80
[ 1331.098170] [<f8610602>] ath_pci_exit+0x12/0x20 [ath9k]
[ 1331.098170] [<f8619ce0>] ath9k_exit+0x17/0x337 [ath9k]
[ 1331.098170] [<c09e537d>] ? mutex_unlock+0xd/0x10
[ 1331.098170] [<c04bd36c>] sys_delete_module+0x17c/0x250
[ 1331.098170] [<c0540dc4>] ? do_munmap+0x244/0x2d0
[ 1331.098170] [<c0540e96>] ? vm_munmap+0x46/0x60
[ 1331.098170] [<c09e8dc4>] ? restore_all+0xf/0xf
[ 1331.098170] [<c09ebf50>] ? __do_page_fault+0x4c0/0x4c0
[ 1331.098170] [<c04b18e4>] ? trace_hardirqs_on_caller+0xf4/0x180
[ 1331.098170] [<c09ef28d>] sysenter_do_call+0x12/0x38
[ 1331.098170] Code: 90 8d 74 26 00 55 89 e5 83 ec 08 89 1c 24 89 74 24 04 3e 82
[ 1331.098170] EIP: [<c063d0d6>] debugfs_remove+0x26/0x80 SS:ESP 0068:ee251e0c
[ 1331.098170] CR2: 000000006b6b6b8b
[ 1331.727971] ---[ end trace b5bb9f2066cef7f9 ]---
Cc: <stable@vger.kernel.org>
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Tested-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/debug.c | 8 ++++++++
drivers/net/wireless/ath/ath9k/debug.h | 5 +++++
drivers/net/wireless/ath/ath9k/init.c | 10 ++++------
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 4101c4a..cecbe1f 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1684,6 +1684,14 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
WARN_ON(i != ATH9K_SSTATS_LEN);
}
+void ath9k_deinit_debug(struct ath_softc *sc)
+{
+ if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+ relay_close(sc->rfs_chan_spec_scan);
+ sc->rfs_chan_spec_scan = NULL;
+ }
+}
+
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 62da19c..223418d 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -297,6 +297,7 @@ struct ath9k_debug {
};
int ath9k_init_debug(struct ath_hw *ah);
+void ath9k_deinit_debug(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
@@ -332,6 +333,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0;
}
+static inline void ath9k_deinit_debug(struct ath_softc *sc)
+{
+}
+
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c7b888f..c0aa4ff 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -903,7 +903,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
if (!ath_is_world_regd(reg)) {
error = regulatory_hint(hw->wiphy, reg->alpha2);
if (error)
- goto unregister;
+ goto debug_cleanup;
}
ath_init_leds(sc);
@@ -911,6 +911,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
return 0;
+debug_cleanup:
+ ath9k_deinit_debug(sc);
unregister:
ieee80211_unregister_hw(hw);
rx_cleanup:
@@ -939,11 +941,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
sc->dfs_detector->exit(sc->dfs_detector);
ath9k_eeprom_release(sc);
-
- if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
- relay_close(sc->rfs_chan_spec_scan);
- sc->rfs_chan_spec_scan = NULL;
- }
}
void ath9k_deinit_device(struct ath_softc *sc)
@@ -957,6 +954,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
ath9k_ps_restore(sc);
+ ath9k_deinit_debug(sc);
ieee80211_unregister_hw(hw);
ath_rx_cleanup(sc);
ath9k_deinit_softc(sc);
--
1.8.2.2
^ permalink raw reply related
* [PATCH] ath9k: Fix crash on module unload
From: Sujith Manoharan @ 2013-05-10 13:08 UTC (permalink / raw)
To: John Linville; +Cc: linux-wireless
From: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Make sure that any open relayfs files are closed before
unregistering with mac80211, otherwise this crash is seen:
[ 1331.097846] BUG: unable to handle kernel paging request at 6b6b6b8b
[ 1331.098170] IP: [<c063d0d6>] debugfs_remove+0x26/0x80
[ 1331.098170] *pdpt = 000000002f9aa001 *pde = 0000000000000000
[ 1331.098170] Oops: 0000 [#1] PREEMPT SMP
[ 1331.098170] Modules linked in: iptable_raw xt_CT nf_conntrack_ipv4 nf_defrag]
[ 1331.098170] Pid: 4794, comm: rmmod Tainted: G WC 3.9.1+ #5 To Be Fi.
[ 1331.098170] EIP: 0060:[<c063d0d6>] EFLAGS: 00010202 CPU: 0
[ 1331.098170] EIP is at debugfs_remove+0x26/0x80
[ 1331.098170] EAX: f2f3acd0 EBX: f2f3acd0 ECX: 00000006 EDX: f8622348
[ 1331.098170] ESI: 6b6b6b6b EDI: 00000001 EBP: ee251e14 ESP: ee251e0c
[ 1331.098170] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068
[ 1331.098170] CR0: 8005003b CR2: 6b6b6b8b CR3: 2e7b7000 CR4: 000007e0
[ 1331.098170] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000
[ 1331.098170] DR6: ffff0ff0 DR7: 00000400
[ 1331.098170] Process rmmod (pid: 4794, ti=ee250000 task=efaa2560 task.ti=ee25)
[ 1331.098170] Stack:
[ 1331.098170] f241e170 0000000a ee251e1c f861394d ee251e28 c04e3088 f241e170 4
[ 1331.098170] c04e30fe f45482b0 ee251e54 c04e3187 f25e86b0 ee251e54 f8618748 0
[ 1331.098170] 0000000a 00000001 ee251e68 f860065b f2509e20 f25085a0 f5b6e8a4 8
[ 1331.098170] Call Trace:
[ 1331.098170] [<f861394d>] remove_buf_file_handler+0xd/0x20 [ath9k]
[ 1331.098170] [<c04e3088>] relay_remove_buf+0x18/0x30
[ 1331.098170] [<c04e30fe>] relay_close_buf+0x2e/0x40
[ 1331.098170] [<c04e3187>] relay_close+0x77/0xf0
[ 1331.098170] [<f8618748>] ? dpd_exit+0x38/0x40 [ath9k]
[ 1331.098170] [<f860065b>] ath9k_deinit_softc+0x8b/0xa0 [ath9k]
[ 1331.098170] [<f86006b8>] ath9k_deinit_device+0x48/0x60 [ath9k]
[ 1331.098170] [<f86107f1>] ath_pci_remove+0x31/0x50 [ath9k]
[ 1331.098170] [<c06dbff8>] pci_device_remove+0x38/0xc0
[ 1331.098170] [<c079daa4>] __device_release_driver+0x64/0xc0
[ 1331.098170] [<c079db97>] driver_detach+0x97/0xa0
[ 1331.098170] [<c079cacc>] bus_remove_driver+0x6c/0xe0
[ 1331.098170] [<c079c197>] ? bus_put+0x17/0x20
[ 1331.098170] [<c079cae3>] ? bus_remove_driver+0x83/0xe0
[ 1331.098170] [<c079e709>] driver_unregister+0x49/0x80
[ 1331.098170] [<c06dc138>] pci_unregister_driver+0x18/0x80
[ 1331.098170] [<f8610602>] ath_pci_exit+0x12/0x20 [ath9k]
[ 1331.098170] [<f8619ce0>] ath9k_exit+0x17/0x337 [ath9k]
[ 1331.098170] [<c09e537d>] ? mutex_unlock+0xd/0x10
[ 1331.098170] [<c04bd36c>] sys_delete_module+0x17c/0x250
[ 1331.098170] [<c0540dc4>] ? do_munmap+0x244/0x2d0
[ 1331.098170] [<c0540e96>] ? vm_munmap+0x46/0x60
[ 1331.098170] [<c09e8dc4>] ? restore_all+0xf/0xf
[ 1331.098170] [<c09ebf50>] ? __do_page_fault+0x4c0/0x4c0
[ 1331.098170] [<c04b18e4>] ? trace_hardirqs_on_caller+0xf4/0x180
[ 1331.098170] [<c09ef28d>] sysenter_do_call+0x12/0x38
[ 1331.098170] Code: 90 8d 74 26 00 55 89 e5 83 ec 08 89 1c 24 89 74 24 04 3e 82
[ 1331.098170] EIP: [<c063d0d6>] debugfs_remove+0x26/0x80 SS:ESP 0068:ee251e0c
[ 1331.098170] CR2: 000000006b6b6b8b
[ 1331.727971] ---[ end trace b5bb9f2066cef7f9 ]---
Acked-by: Simon Wunderlich <siwu@hrz.tu-chemnitz.de>
Tested-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
---
drivers/net/wireless/ath/ath9k/debug.c | 8 ++++++++
drivers/net/wireless/ath/ath9k/debug.h | 5 +++++
drivers/net/wireless/ath/ath9k/init.c | 10 ++++------
3 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 4101c4a..cecbe1f 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1684,6 +1684,14 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw,
WARN_ON(i != ATH9K_SSTATS_LEN);
}
+void ath9k_deinit_debug(struct ath_softc *sc)
+{
+ if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
+ relay_close(sc->rfs_chan_spec_scan);
+ sc->rfs_chan_spec_scan = NULL;
+ }
+}
+
int ath9k_init_debug(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 62da19c..223418d 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -297,6 +297,7 @@ struct ath9k_debug {
};
int ath9k_init_debug(struct ath_hw *ah);
+void ath9k_deinit_debug(struct ath_softc *sc);
void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
@@ -332,6 +333,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah)
return 0;
}
+static inline void ath9k_deinit_debug(struct ath_softc *sc)
+{
+}
+
static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
enum ath9k_int status)
{
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index c7b888f..c0aa4ff 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -903,7 +903,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
if (!ath_is_world_regd(reg)) {
error = regulatory_hint(hw->wiphy, reg->alpha2);
if (error)
- goto unregister;
+ goto debug_cleanup;
}
ath_init_leds(sc);
@@ -911,6 +911,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
return 0;
+debug_cleanup:
+ ath9k_deinit_debug(sc);
unregister:
ieee80211_unregister_hw(hw);
rx_cleanup:
@@ -939,11 +941,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
sc->dfs_detector->exit(sc->dfs_detector);
ath9k_eeprom_release(sc);
-
- if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) {
- relay_close(sc->rfs_chan_spec_scan);
- sc->rfs_chan_spec_scan = NULL;
- }
}
void ath9k_deinit_device(struct ath_softc *sc)
@@ -957,6 +954,7 @@ void ath9k_deinit_device(struct ath_softc *sc)
ath9k_ps_restore(sc);
+ ath9k_deinit_debug(sc);
ieee80211_unregister_hw(hw);
ath_rx_cleanup(sc);
ath9k_deinit_softc(sc);
--
1.8.2.2
^ permalink raw reply related
* Re: [RFC 4/4] cfg80211/mac80211: use cfg80211 wdev mutex in mac80211
From: Johannes Berg @ 2013-05-10 12:26 UTC (permalink / raw)
To: Arend van Spriel; +Cc: linux-wireless, greearb
In-Reply-To: <518CE683.2040402@broadcom.com>
On Fri, 2013-05-10 at 14:22 +0200, Arend van Spriel wrote:
> On 05/10/2013 02:08 PM, Johannes Berg wrote:
> > From: Johannes Berg <johannes.berg@intel.com>
> >
> > Using separate locks in cfg80211 and mac80211 has always
> > caused issues, for example having to unlock in places in
> > mac80211 to call cfg80211, which even needed a framework
> > to make cfg80211 calls after some functions returned etc.
> >
> > Additionally, I suspect some issues people have reported
> > with the cfg80211 state getting confused could be due to
> > such issues, when cfg80211 is asking mac80211 to change
> > state but mac80211 is in the process of telling cfg80211
> > that the state changed (in another way.)
>
> I guess this change affects fullmac drivers like brcmfmac, right?
I don't think so.
johannes
^ permalink raw reply
* Re: [RFC 4/4] cfg80211/mac80211: use cfg80211 wdev mutex in mac80211
From: Arend van Spriel @ 2013-05-10 12:22 UTC (permalink / raw)
To: Johannes Berg; +Cc: linux-wireless, greearb, Johannes Berg
In-Reply-To: <1368187689-29706-5-git-send-email-johannes@sipsolutions.net>
On 05/10/2013 02:08 PM, Johannes Berg wrote:
> From: Johannes Berg <johannes.berg@intel.com>
>
> Using separate locks in cfg80211 and mac80211 has always
> caused issues, for example having to unlock in places in
> mac80211 to call cfg80211, which even needed a framework
> to make cfg80211 calls after some functions returned etc.
>
> Additionally, I suspect some issues people have reported
> with the cfg80211 state getting confused could be due to
> such issues, when cfg80211 is asking mac80211 to change
> state but mac80211 is in the process of telling cfg80211
> that the state changed (in another way.)
I guess this change affects fullmac drivers like brcmfmac, right?
Gr. AvS
^ permalink raw reply
* Re: [RFC 0/4] cfg80211/mac80211: simplify locking
From: Johannes Berg @ 2013-05-10 12:09 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
On Fri, 2013-05-10 at 14:08 +0200, Johannes Berg wrote:
> I got a little fed up with all the locking, and decided to simplify.
>
> This should still work, but I've only done some very simple tests.
> I'm hoping it'll fix some of the weird corner cases that Ben and
> others have found, which may be due to different locks in different
> cases and things racing against each other ... I'm not convinced it
> really will though, but hey, who knows :)
Of course, this is also always a good thing:
24 files changed, 322 insertions(+), 803 deletions(-)
johannes
^ permalink raw reply
* [RFC 4/4] cfg80211/mac80211: use cfg80211 wdev mutex in mac80211
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Using separate locks in cfg80211 and mac80211 has always
caused issues, for example having to unlock in places in
mac80211 to call cfg80211, which even needed a framework
to make cfg80211 calls after some functions returned etc.
Additionally, I suspect some issues people have reported
with the cfg80211 state getting confused could be due to
such issues, when cfg80211 is asking mac80211 to change
state but mac80211 is in the process of telling cfg80211
that the state changed (in another way.)
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
Documentation/DocBook/80211.tmpl | 2 -
include/net/cfg80211.h | 41 ++---
net/mac80211/cfg.c | 4 +-
net/mac80211/debugfs_netdev.c | 10 +-
net/mac80211/ht.c | 4 +-
net/mac80211/ibss.c | 39 ++---
net/mac80211/ieee80211_i.h | 25 ++-
net/mac80211/main.c | 4 +-
net/mac80211/mlme.c | 332 ++++++++++++++-------------------------
net/mac80211/util.c | 4 +-
net/wireless/mlme.c | 48 +-----
net/wireless/trace.h | 4 +-
12 files changed, 186 insertions(+), 331 deletions(-)
diff --git a/Documentation/DocBook/80211.tmpl b/Documentation/DocBook/80211.tmpl
index 0f6a3ed..ebe8969 100644
--- a/Documentation/DocBook/80211.tmpl
+++ b/Documentation/DocBook/80211.tmpl
@@ -132,9 +132,7 @@
!Finclude/net/cfg80211.h cfg80211_send_rx_assoc
!Finclude/net/cfg80211.h cfg80211_send_assoc_timeout
!Finclude/net/cfg80211.h cfg80211_send_deauth
-!Finclude/net/cfg80211.h __cfg80211_send_deauth
!Finclude/net/cfg80211.h cfg80211_send_disassoc
-!Finclude/net/cfg80211.h __cfg80211_send_disassoc
!Finclude/net/cfg80211.h cfg80211_ibss_joined
!Finclude/net/cfg80211.h cfg80211_connect_result
!Finclude/net/cfg80211.h cfg80211_roamed
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 085e5f7..0959fed 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -2849,7 +2849,8 @@ struct cfg80211_cached_keys;
* by cfg80211 on change_interface
* @mgmt_registrations: list of registrations for management frames
* @mgmt_registrations_lock: lock for the list
- * @mtx: mutex used to lock data in this struct
+ * @mtx: mutex used to lock data in this struct, may be used by drivers
+ * and some API functions require it held
* @cleanup_work: work struct used for cleanup that can't be done directly
* @beacon_interval: beacon interval used on this device for transmitting
* beacons, 0 when not valid
@@ -3413,7 +3414,8 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *bss);
* This function is called whenever an authentication has been processed in
* station mode. The driver is required to call either this function or
* cfg80211_send_auth_timeout() to indicate the result of cfg80211_ops::auth()
- * call. This function may sleep.
+ * call. This function may sleep. The caller must hold the corresponding wdev's
+ * mutex.
*/
void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
@@ -3422,7 +3424,8 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len);
* @dev: network device
* @addr: The MAC address of the device with which the authentication timed out
*
- * This function may sleep.
+ * This function may sleep. The caller must hold the corresponding wdev's
+ * mutex.
*/
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
@@ -3437,7 +3440,8 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr);
* This function is called whenever a (re)association response has been
* processed in station mode. The driver is required to call either this
* function or cfg80211_send_assoc_timeout() to indicate the result of
- * cfg80211_ops::assoc() call. This function may sleep.
+ * cfg80211_ops::assoc() call. This function may sleep. The caller must hold
+ * the corresponding wdev's mutex.
*/
void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
const u8 *buf, size_t len);
@@ -3447,7 +3451,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* @dev: network device
* @addr: The MAC address of the device with which the association timed out
*
- * This function may sleep.
+ * This function may sleep. The caller must hold the corresponding wdev's mutex.
*/
void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
@@ -3459,21 +3463,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr);
*
* This function is called whenever deauthentication has been processed in
* station mode. This includes both received deauthentication frames and
- * locally generated ones. This function may sleep.
+ * locally generated ones. This function may sleep. The caller must hold the
+ * corresponding wdev's mutex.
*/
void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
/**
- * __cfg80211_send_deauth - notification of processed deauthentication
- * @dev: network device
- * @buf: deauthentication frame (header + body)
- * @len: length of the frame data
- *
- * Like cfg80211_send_deauth(), but doesn't take the wdev lock.
- */
-void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
-
-/**
* cfg80211_send_disassoc - notification of processed disassociation
* @dev: network device
* @buf: disassociation response frame (header + body)
@@ -3481,22 +3476,12 @@ void __cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len);
*
* This function is called whenever disassociation has been processed in
* station mode. This includes both received disassociation frames and locally
- * generated ones. This function may sleep.
+ * generated ones. This function may sleep. The caller must hold the
+ * corresponding wdev's mutex.
*/
void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len);
/**
- * __cfg80211_send_disassoc - notification of processed disassociation
- * @dev: network device
- * @buf: disassociation response frame (header + body)
- * @len: length of the frame data
- *
- * Like cfg80211_send_disassoc(), but doesn't take the wdev lock.
- */
-void __cfg80211_send_disassoc(struct net_device *dev, const u8 *buf,
- size_t len);
-
-/**
* cfg80211_send_unprot_deauth - notification of unprotected deauthentication
* @dev: network device
* @buf: deauthentication frame (header + body)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6698945..a8e4ba1 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2317,7 +2317,7 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
enum ieee80211_smps_mode old_req;
int err;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ lockdep_assert_held(&sdata->wdev.mtx);
old_req = sdata->u.mgd.req_smps;
sdata->u.mgd.req_smps = smps_mode;
@@ -2374,9 +2374,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
local->dynamic_ps_forced_timeout = timeout;
/* no change, but if automatic follow powersave */
- mutex_lock(&sdata->u.mgd.mtx);
__ieee80211_request_smps(sdata, sdata->u.mgd.req_smps);
- mutex_unlock(&sdata->u.mgd.mtx);
if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c
index 14abcf4..27d08ec 100644
--- a/net/mac80211/debugfs_netdev.c
+++ b/net/mac80211/debugfs_netdev.c
@@ -228,9 +228,9 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
if (sdata->vif.type != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
err = __ieee80211_request_smps(sdata, smps_mode);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
return err;
}
@@ -313,16 +313,16 @@ static ssize_t ieee80211_if_parse_tkip_mic_test(
case NL80211_IFTYPE_STATION:
fc |= cpu_to_le16(IEEE80211_FCTL_TODS);
/* BSSID SA DA */
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
if (!sdata->u.mgd.associated) {
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
dev_kfree_skb(skb);
return -ENOTCONN;
}
memcpy(hdr->addr1, sdata->u.mgd.associated->bssid, ETH_ALEN);
memcpy(hdr->addr2, sdata->vif.addr, ETH_ALEN);
memcpy(hdr->addr3, addr, ETH_ALEN);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
break;
default:
dev_kfree_skb(skb);
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index af8cee0..75dff33 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -429,9 +429,9 @@ void ieee80211_request_smps_work(struct work_struct *work)
container_of(work, struct ieee80211_sub_if_data,
u.mgd.request_smps_work);
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
__ieee80211_request_smps(sdata, sdata->u.mgd.driver_smps_mode);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
}
void ieee80211_request_smps(struct ieee80211_vif *vif,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 170f9a7..3b305f3 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -54,7 +54,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
int frame_len;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
/* Reset own TSF to allow time synchronization work. */
drv_reset_tsf(local, sdata);
@@ -74,7 +74,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
}
presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&ifibss->mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
rcu_assign_pointer(ifibss->presp, NULL);
if (presp)
kfree_rcu(presp, rcu_head);
@@ -263,7 +263,7 @@ static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata,
const struct cfg80211_bss_ies *ies;
u64 tsf;
- lockdep_assert_held(&sdata->u.ibss.mtx);
+ sdata_assert_lock(sdata);
if (beacon_int < 10)
beacon_int = 10;
@@ -408,7 +408,7 @@ static void ieee80211_rx_mgmt_auth_ibss(struct ieee80211_sub_if_data *sdata,
struct sta_info *sta;
u8 deauth_frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- lockdep_assert_held(&sdata->u.ibss.mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 6)
return;
@@ -673,7 +673,7 @@ static int ieee80211_sta_active_ibss(struct ieee80211_sub_if_data *sdata)
int active = 0;
struct sta_info *sta;
- lockdep_assert_held(&sdata->u.ibss.mtx);
+ sdata_assert_lock(sdata);
rcu_read_lock();
@@ -699,7 +699,7 @@ static void ieee80211_sta_merge_ibss(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
mod_timer(&ifibss->timer,
round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL));
@@ -730,7 +730,7 @@ static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
u16 capability;
int i;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
if (ifibss->fixed_bssid) {
memcpy(bssid, ifibss->bssid, ETH_ALEN);
@@ -773,7 +773,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata)
int active_ibss;
u16 capability;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
active_ibss = ieee80211_sta_active_ibss(sdata);
ibss_dbg(sdata, "sta_find_ibss (active_ibss=%d)\n", active_ibss);
@@ -843,10 +843,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata,
struct beacon_data *presp;
u8 *pos, *end;
- lockdep_assert_held(&ifibss->mtx);
+ sdata_assert_lock(sdata);
presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&ifibss->mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
if (ifibss->state != IEEE80211_IBSS_MLME_JOINED ||
len < 24 + 2 || !presp)
@@ -930,7 +930,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
- mutex_lock(&sdata->u.ibss.mtx);
+ sdata_lock(sdata);
if (!sdata->u.ibss.ssid_len)
goto mgmt_out; /* not ready to merge yet */
@@ -953,7 +953,7 @@ void ieee80211_ibss_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}
mgmt_out:
- mutex_unlock(&sdata->u.ibss.mtx);
+ sdata_unlock(sdata);
}
void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
@@ -961,7 +961,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct sta_info *sta;
- mutex_lock(&ifibss->mtx);
+ sdata_lock(sdata);
/*
* Work could be scheduled after scan or similar
@@ -997,7 +997,7 @@ void ieee80211_ibss_work(struct ieee80211_sub_if_data *sdata)
}
out:
- mutex_unlock(&ifibss->mtx);
+ sdata_unlock(sdata);
}
static void ieee80211_ibss_timer(unsigned long data)
@@ -1014,7 +1014,6 @@ void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
setup_timer(&ifibss->timer, ieee80211_ibss_timer,
(unsigned long) sdata);
- mutex_init(&ifibss->mtx);
INIT_LIST_HEAD(&ifibss->incomplete_stations);
spin_lock_init(&ifibss->incomplete_lock);
}
@@ -1041,8 +1040,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
{
u32 changed = 0;
- mutex_lock(&sdata->u.ibss.mtx);
-
if (params->bssid) {
memcpy(sdata->u.ibss.bssid, params->bssid, ETH_ALEN);
sdata->u.ibss.fixed_bssid = true;
@@ -1075,8 +1072,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
memcpy(sdata->u.ibss.ssid, params->ssid, params->ssid_len);
sdata->u.ibss.ssid_len = params->ssid_len;
- mutex_unlock(&sdata->u.ibss.mtx);
-
/*
* 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
* reserved, but an HT STA shall protect HT transmissions as though
@@ -1112,8 +1107,6 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
struct sta_info *sta;
struct beacon_data *presp;
- mutex_lock(&sdata->u.ibss.mtx);
-
active_ibss = ieee80211_sta_active_ibss(sdata);
if (!active_ibss && !is_zero_ether_addr(ifibss->bssid)) {
@@ -1157,7 +1150,7 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
/* remove beacon */
kfree(sdata->u.ibss.ie);
presp = rcu_dereference_protected(ifibss->presp,
- lockdep_is_held(&sdata->u.ibss.mtx));
+ lockdep_is_held(&sdata->wdev.mtx));
RCU_INIT_POINTER(sdata->u.ibss.presp, NULL);
sdata->vif.bss_conf.ibss_joined = false;
sdata->vif.bss_conf.ibss_creator = false;
@@ -1173,7 +1166,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
del_timer_sync(&sdata->u.ibss.timer);
- mutex_unlock(&sdata->u.ibss.mtx);
-
return 0;
}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 44be28cfc..2e75459 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -394,7 +394,6 @@ struct ieee80211_if_managed {
bool nullfunc_failed;
bool connection_loss;
- struct mutex mtx;
struct cfg80211_bss *associated;
struct ieee80211_mgd_auth_data *auth_data;
struct ieee80211_mgd_assoc_data *assoc_data;
@@ -488,8 +487,6 @@ struct ieee80211_if_managed {
struct ieee80211_if_ibss {
struct timer_list timer;
- struct mutex mtx;
-
unsigned long last_scan_completed;
u32 basic_rates;
@@ -580,8 +577,6 @@ struct ieee80211_if_mesh {
bool accepting_plinks;
int num_gates;
struct beacon_data __rcu *beacon;
- /* just protects beacon updates for now */
- struct mutex mtx;
const u8 *ie;
u8 ie_len;
enum {
@@ -778,6 +773,26 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
return container_of(p, struct ieee80211_sub_if_data, vif);
}
+static inline void sdata_lock(struct ieee80211_sub_if_data *sdata)
+ __acquires(&sdata->wdev.mtx)
+{
+ mutex_lock(&sdata->wdev.mtx);
+ __acquire(&sdata->wdev.mtx);
+}
+
+static inline void sdata_unlock(struct ieee80211_sub_if_data *sdata)
+ __releases(&sdata->wdev.mtx)
+{
+ mutex_unlock(&sdata->wdev.mtx);
+ __release(&sdata->wdev.mtx);
+}
+
+static inline void
+sdata_assert_lock(struct ieee80211_sub_if_data *sdata)
+{
+ lockdep_assert_held(&sdata->wdev.mtx);
+}
+
static inline enum ieee80211_band
ieee80211_get_sdata_band(struct ieee80211_sub_if_data *sdata)
{
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 8a7bfc4..1998f14 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -331,7 +331,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
return NOTIFY_DONE;
ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
/* Copy the addresses to the bss_conf list */
ifa = idev->ifa_list;
@@ -349,7 +349,7 @@ static int ieee80211_ifa_changed(struct notifier_block *nb,
ieee80211_bss_info_change_notify(sdata,
BSS_CHANGED_ARP_FILTER);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return NOTIFY_DONE;
}
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 07a3eb5..889d64b 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -91,41 +91,6 @@ MODULE_PARM_DESC(probe_wait_ms,
#define IEEE80211_SIGNAL_AVE_MIN_COUNT 4
/*
- * All cfg80211 functions have to be called outside a locked
- * section so that they can acquire a lock themselves... This
- * is much simpler than queuing up things in cfg80211, but we
- * do need some indirection for that here.
- */
-enum rx_mgmt_action {
- /* no action required */
- RX_MGMT_NONE,
-
- /* caller must call cfg80211_send_deauth() */
- RX_MGMT_CFG80211_DEAUTH,
-
- /* caller must call cfg80211_send_disassoc() */
- RX_MGMT_CFG80211_DISASSOC,
-
- /* caller must call cfg80211_send_rx_auth() */
- RX_MGMT_CFG80211_RX_AUTH,
-
- /* caller must call cfg80211_send_rx_assoc() */
- RX_MGMT_CFG80211_RX_ASSOC,
-
- /* caller must call cfg80211_send_assoc_timeout() */
- RX_MGMT_CFG80211_ASSOC_TIMEOUT,
-
- /* used when a processed beacon causes a deauth */
- RX_MGMT_CFG80211_TX_DEAUTH,
-};
-
-/* utils */
-static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
-{
- lockdep_assert_held(&ifmgd->mtx);
-}
-
-/*
* We can have multiple work items (and connection probing)
* scheduling this timer, but we need to take care to only
* reschedule it when it should fire _earlier_ than it was
@@ -135,13 +100,14 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd)
* has happened -- the work that runs from this timer will
* do that.
*/
-static void run_again(struct ieee80211_if_managed *ifmgd, unsigned long timeout)
+static void run_again(struct ieee80211_sub_if_data *sdata,
+ unsigned long timeout)
{
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
- if (!timer_pending(&ifmgd->timer) ||
- time_before(timeout, ifmgd->timer.expires))
- mod_timer(&ifmgd->timer, timeout);
+ if (!timer_pending(&sdata->u.mgd.timer) ||
+ time_before(timeout, sdata->u.mgd.timer.expires))
+ mod_timer(&sdata->u.mgd.timer, timeout);
}
void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata)
@@ -652,7 +618,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_channel *chan;
u32 rates = 0;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
@@ -962,7 +928,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
if (!ieee80211_sdata_running(sdata))
return;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated)
goto out;
@@ -985,7 +951,7 @@ static void ieee80211_chswitch_work(struct work_struct *work)
IEEE80211_QUEUE_STOP_REASON_CSA);
out:
ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED;
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success)
@@ -1036,7 +1002,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
const struct ieee80211_ht_operation *ht_oper;
int secondary_channel_offset = -1;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (!cbss)
return;
@@ -1845,7 +1811,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
struct ieee80211_local *local = sdata->local;
u32 changed = 0;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (WARN_ON_ONCE(tx && !frame_buf))
return;
@@ -2054,7 +2020,7 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
}
ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
- run_again(ifmgd, ifmgd->probe_timeout);
+ run_again(sdata, ifmgd->probe_timeout);
if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
ieee80211_flush_queues(sdata->local, sdata);
}
@@ -2068,7 +2034,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
if (!ieee80211_sdata_running(sdata))
return;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated)
goto out;
@@ -2122,7 +2088,7 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
ifmgd->probe_send_count = 0;
ieee80211_mgd_probe_ap_send(sdata);
out:
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
@@ -2138,7 +2104,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
return NULL;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (ifmgd->associated)
cbss = ifmgd->associated;
@@ -2171,9 +2137,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
@@ -2184,13 +2150,9 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
ieee80211_wake_queues_by_reason(&sdata->local->hw,
IEEE80211_MAX_QUEUE_MAP,
IEEE80211_QUEUE_STOP_REASON_CSA);
- mutex_unlock(&ifmgd->mtx);
- /*
- * must be outside lock due to cfg80211,
- * but that's not a problem.
- */
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
+ sdata_unlock(sdata);
}
static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -2257,7 +2219,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_mgd_auth_data *auth_data = sdata->u.mgd.auth_data;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if (!assoc) {
sta_info_destroy_addr(sdata, auth_data->bss->bssid);
@@ -2298,27 +2260,26 @@ static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
auth_data->key_idx, tx_flags);
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 bssid[ETH_ALEN];
u16 auth_alg, auth_transaction, status_code;
struct sta_info *sta;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 6)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->auth_data || ifmgd->auth_data->done)
- return RX_MGMT_NONE;
+ return;
memcpy(bssid, ifmgd->auth_data->bss->bssid, ETH_ALEN);
if (!ether_addr_equal(bssid, mgmt->bssid))
- return RX_MGMT_NONE;
+ return;
auth_alg = le16_to_cpu(mgmt->u.auth.auth_alg);
auth_transaction = le16_to_cpu(mgmt->u.auth.auth_transaction);
@@ -2330,14 +2291,15 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
mgmt->sa, auth_alg, ifmgd->auth_data->algorithm,
auth_transaction,
ifmgd->auth_data->expected_transaction);
- return RX_MGMT_NONE;
+ return;
}
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied authentication (status %d)\n",
mgmt->sa, status_code);
ieee80211_destroy_auth_data(sdata, false);
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
}
switch (ifmgd->auth_data->algorithm) {
@@ -2350,20 +2312,20 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
if (ifmgd->auth_data->expected_transaction != 4) {
ieee80211_auth_challenge(sdata, mgmt, len);
/* need another frame */
- return RX_MGMT_NONE;
+ return;
}
break;
default:
WARN_ONCE(1, "invalid auth alg %d",
ifmgd->auth_data->algorithm);
- return RX_MGMT_NONE;
+ return;
}
sdata_info(sdata, "authenticated\n");
ifmgd->auth_data->done = true;
ifmgd->auth_data->timeout = jiffies + IEEE80211_AUTH_WAIT_ASSOC;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
if (ifmgd->auth_data->algorithm == WLAN_AUTH_SAE &&
ifmgd->auth_data->expected_transaction != 2) {
@@ -2371,7 +2333,8 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
* Report auth frame to user space for processing since another
* round of Authentication frames is still needed.
*/
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
}
/* move station state to auth */
@@ -2387,30 +2350,29 @@ ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata,
}
mutex_unlock(&sdata->local->sta_mtx);
- return RX_MGMT_CFG80211_RX_AUTH;
+ cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, len);
+ return;
out_err:
mutex_unlock(&sdata->local->sta_mtx);
/* ignore frame -- wait for timeout */
- return RX_MGMT_NONE;
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
const u8 *bssid = NULL;
u16 reason_code;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 2)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
bssid = ifmgd->associated->bssid;
@@ -2421,25 +2383,24 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- return RX_MGMT_CFG80211_DEAUTH;
+ cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, len);
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len)
+static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u16 reason_code;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (len < 24 + 2)
- return RX_MGMT_NONE;
+ return;
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code);
@@ -2448,7 +2409,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
- return RX_MGMT_CFG80211_DISASSOC;
+ cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, len);
}
static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
@@ -2498,7 +2459,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
{
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if (!assoc) {
sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
@@ -2679,10 +2640,9 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
return true;
}
-static enum rx_mgmt_action __must_check
-ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len,
- struct cfg80211_bss **bss)
+static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt,
+ size_t len)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_mgd_assoc_data *assoc_data = ifmgd->assoc_data;
@@ -2690,13 +2650,14 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
struct ieee802_11_elems elems;
u8 *pos;
bool reassoc;
+ struct cfg80211_bss *bss;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (!assoc_data)
- return RX_MGMT_NONE;
+ return;
if (!ether_addr_equal(assoc_data->bss->bssid, mgmt->bssid))
- return RX_MGMT_NONE;
+ return;
/*
* AssocResp and ReassocResp have identical structure, so process both
@@ -2704,7 +2665,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
*/
if (len < 24 + 6)
- return RX_MGMT_NONE;
+ return;
reassoc = ieee80211_is_reassoc_req(mgmt->frame_control);
capab_info = le16_to_cpu(mgmt->u.assoc_resp.capab_info);
@@ -2731,22 +2692,23 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
assoc_data->timeout = jiffies + msecs_to_jiffies(ms);
assoc_data->timeout_started = true;
if (ms > IEEE80211_ASSOC_TIMEOUT)
- run_again(ifmgd, assoc_data->timeout);
- return RX_MGMT_NONE;
+ run_again(sdata, assoc_data->timeout);
+ return;
}
- *bss = assoc_data->bss;
+ bss = assoc_data->bss;
if (status_code != WLAN_STATUS_SUCCESS) {
sdata_info(sdata, "%pM denied association (code=%d)\n",
mgmt->sa, status_code);
ieee80211_destroy_assoc_data(sdata, false);
} else {
- if (!ieee80211_assoc_success(sdata, *bss, mgmt, len)) {
+ if (!ieee80211_assoc_success(sdata, bss, mgmt, len)) {
/* oops -- internal error -- send timeout for now */
ieee80211_destroy_assoc_data(sdata, false);
- cfg80211_put_bss(sdata->local->hw.wiphy, *bss);
- return RX_MGMT_CFG80211_ASSOC_TIMEOUT;
+ cfg80211_put_bss(sdata->local->hw.wiphy, bss);
+ cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
+ return;
}
sdata_info(sdata, "associated\n");
@@ -2758,7 +2720,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
ieee80211_destroy_assoc_data(sdata, true);
}
- return RX_MGMT_CFG80211_RX_ASSOC;
+ cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, len);
}
static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
@@ -2772,7 +2734,7 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel *channel;
bool need_ps = false;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
if ((sdata->u.mgd.associated &&
ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
@@ -2831,7 +2793,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd = &sdata->u.mgd;
- ASSERT_MGD_MTX(ifmgd);
+ sdata_assert_lock(sdata);
if (!ether_addr_equal(mgmt->da, sdata->vif.addr))
return; /* ignore ProbeResp to foreign address */
@@ -2856,7 +2818,7 @@ static void ieee80211_rx_mgmt_probe_resp(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data->tries = 0;
ifmgd->auth_data->timeout = jiffies;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
}
}
@@ -2881,10 +2843,10 @@ static const u64 care_about_ies =
(1ULL << WLAN_EID_HT_CAPABILITY) |
(1ULL << WLAN_EID_HT_OPERATION);
-static enum rx_mgmt_action
-ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
- struct ieee80211_mgmt *mgmt, size_t len,
- u8 *deauth_buf, struct ieee80211_rx_status *rx_status)
+static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
+ struct ieee80211_mgmt *mgmt, size_t len,
+ u8 *deauth_buf,
+ struct ieee80211_rx_status *rx_status)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
@@ -2900,23 +2862,23 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
u32 ncrc;
u8 *bssid;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
/* Process beacon from the current BSS */
baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt;
if (baselen > len)
- return RX_MGMT_NONE;
+ return;
rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
- return RX_MGMT_NONE;
+ return;
}
if (rx_status->freq != chanctx_conf->def.chan->center_freq) {
rcu_read_unlock();
- return RX_MGMT_NONE;
+ return;
}
chan = chanctx_conf->def.chan;
rcu_read_unlock();
@@ -2943,13 +2905,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
/* continue assoc process */
ifmgd->assoc_data->timeout = jiffies;
ifmgd->assoc_data->timeout_started = true;
- run_again(ifmgd, ifmgd->assoc_data->timeout);
- return RX_MGMT_NONE;
+ run_again(sdata, ifmgd->assoc_data->timeout);
+ return;
}
if (!ifmgd->associated ||
!ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
- return RX_MGMT_NONE;
+ return;
bssid = ifmgd->associated->bssid;
/* Track average RSSI from the Beacon frames of the current AP */
@@ -3095,7 +3057,7 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
}
if (ncrc == ifmgd->beacon_crc && ifmgd->beacon_crc_valid)
- return RX_MGMT_NONE;
+ return;
ifmgd->beacon_crc = ncrc;
ifmgd->beacon_crc_valid = true;
@@ -3151,7 +3113,9 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
WLAN_REASON_DEAUTH_LEAVING,
true, deauth_buf);
- return RX_MGMT_CFG80211_TX_DEAUTH;
+ cfg80211_send_deauth(sdata->dev, deauth_buf,
+ sizeof(deauth_buf));
+ return;
}
if (sta && elems.opmode_notif)
@@ -3168,18 +3132,13 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
elems.pwr_constr_elem);
ieee80211_bss_info_change_notify(sdata, changed);
-
- return RX_MGMT_NONE;
}
void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_rx_status *rx_status;
struct ieee80211_mgmt *mgmt;
- struct cfg80211_bss *bss = NULL;
- enum rx_mgmt_action rma = RX_MGMT_NONE;
u8 deauth_buf[IEEE80211_DEAUTH_FRAME_LEN];
u16 fc;
struct ieee802_11_elems elems;
@@ -3189,28 +3148,28 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
mgmt = (struct ieee80211_mgmt *) skb->data;
fc = le16_to_cpu(mgmt->frame_control);
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
switch (fc & IEEE80211_FCTL_STYPE) {
case IEEE80211_STYPE_BEACON:
- rma = ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
- deauth_buf, rx_status);
+ ieee80211_rx_mgmt_beacon(sdata, mgmt, skb->len,
+ deauth_buf, rx_status);
break;
case IEEE80211_STYPE_PROBE_RESP:
ieee80211_rx_mgmt_probe_resp(sdata, skb);
break;
case IEEE80211_STYPE_AUTH:
- rma = ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_auth(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_DEAUTH:
- rma = ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_deauth(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_DISASSOC:
- rma = ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
+ ieee80211_rx_mgmt_disassoc(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ASSOC_RESP:
case IEEE80211_STYPE_REASSOC_RESP:
- rma = ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len, &bss);
+ ieee80211_rx_mgmt_assoc_resp(sdata, mgmt, skb->len);
break;
case IEEE80211_STYPE_ACTION:
if (mgmt->u.action.category == WLAN_CATEGORY_SPECTRUM_MGMT) {
@@ -3256,34 +3215,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
}
break;
}
- mutex_unlock(&ifmgd->mtx);
-
- switch (rma) {
- case RX_MGMT_NONE:
- /* no action */
- break;
- case RX_MGMT_CFG80211_DEAUTH:
- cfg80211_send_deauth(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_DISASSOC:
- cfg80211_send_disassoc(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_RX_AUTH:
- cfg80211_send_rx_auth(sdata->dev, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_RX_ASSOC:
- cfg80211_send_rx_assoc(sdata->dev, bss, (u8 *)mgmt, skb->len);
- break;
- case RX_MGMT_CFG80211_ASSOC_TIMEOUT:
- cfg80211_send_assoc_timeout(sdata->dev, mgmt->bssid);
- break;
- case RX_MGMT_CFG80211_TX_DEAUTH:
- cfg80211_send_deauth(sdata->dev, deauth_buf,
- sizeof(deauth_buf));
- break;
- default:
- WARN(1, "unexpected: %d", rma);
- }
+ sdata_unlock(sdata);
}
static void ieee80211_sta_timer(unsigned long data)
@@ -3297,20 +3229,12 @@ static void ieee80211_sta_timer(unsigned long data)
static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
u8 *bssid, u8 reason, bool tx)
{
- struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, reason,
tx, frame_buf);
- mutex_unlock(&ifmgd->mtx);
- /*
- * must be outside lock due to cfg80211,
- * but that's not a problem.
- */
cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
-
- mutex_lock(&ifmgd->mtx);
}
static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
@@ -3320,7 +3244,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_auth_data *auth_data = ifmgd->auth_data;
u32 tx_flags = 0;
- lockdep_assert_held(&ifmgd->mtx);
+ sdata_assert_lock(sdata);
if (WARN_ON_ONCE(!auth_data))
return -EINVAL;
@@ -3393,7 +3317,7 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata)
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
ifmgd->auth_data->timeout_started = true;
- run_again(ifmgd, auth_data->timeout);
+ run_again(sdata, auth_data->timeout);
} else {
auth_data->timeout_started = false;
}
@@ -3406,7 +3330,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
struct ieee80211_local *local = sdata->local;
- lockdep_assert_held(&sdata->u.mgd.mtx);
+ sdata_assert_lock(sdata);
assoc_data->tries++;
if (assoc_data->tries > IEEE80211_ASSOC_MAX_TRIES) {
@@ -3430,7 +3354,7 @@ static int ieee80211_do_assoc(struct ieee80211_sub_if_data *sdata)
if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) {
assoc_data->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT;
assoc_data->timeout_started = true;
- run_again(&sdata->u.mgd, assoc_data->timeout);
+ run_again(sdata, assoc_data->timeout);
} else {
assoc_data->timeout_started = false;
}
@@ -3455,7 +3379,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
struct ieee80211_local *local = sdata->local;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (ifmgd->status_received) {
__le16 fc = ifmgd->status_fc;
@@ -3467,7 +3391,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (status_acked) {
ifmgd->auth_data->timeout =
jiffies + IEEE80211_AUTH_TIMEOUT_SHORT;
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
} else {
ifmgd->auth_data->timeout = jiffies - 1;
}
@@ -3478,7 +3402,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
if (status_acked) {
ifmgd->assoc_data->timeout =
jiffies + IEEE80211_ASSOC_TIMEOUT_SHORT;
- run_again(ifmgd, ifmgd->assoc_data->timeout);
+ run_again(sdata, ifmgd->assoc_data->timeout);
} else {
ifmgd->assoc_data->timeout = jiffies - 1;
}
@@ -3501,12 +3425,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
cfg80211_send_auth_timeout(sdata->dev, bssid);
- mutex_lock(&ifmgd->mtx);
}
} else if (ifmgd->auth_data && ifmgd->auth_data->timeout_started)
- run_again(ifmgd, ifmgd->auth_data->timeout);
+ run_again(sdata, ifmgd->auth_data->timeout);
if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started &&
time_after(jiffies, ifmgd->assoc_data->timeout)) {
@@ -3519,12 +3441,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
ieee80211_destroy_assoc_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
cfg80211_send_assoc_timeout(sdata->dev, bssid);
- mutex_lock(&ifmgd->mtx);
}
} else if (ifmgd->assoc_data && ifmgd->assoc_data->timeout_started)
- run_again(ifmgd, ifmgd->assoc_data->timeout);
+ run_again(sdata, ifmgd->assoc_data->timeout);
if (ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
IEEE80211_STA_CONNECTION_POLL) &&
@@ -3558,7 +3478,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
false);
}
} else if (time_is_after_jiffies(ifmgd->probe_timeout))
- run_again(ifmgd, ifmgd->probe_timeout);
+ run_again(sdata, ifmgd->probe_timeout);
else if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) {
mlme_dbg(sdata,
"Failed to send nullfunc to AP %pM after %dms, disconnecting\n",
@@ -3587,7 +3507,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
}
}
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -3648,9 +3568,9 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (!ifmgd->associated) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
@@ -3661,10 +3581,10 @@ void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
ifmgd->associated->bssid,
WLAN_REASON_UNSPECIFIED,
true);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return;
}
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
#endif
@@ -3696,8 +3616,6 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
ifmgd->uapsd_max_sp_len = sdata->local->hw.uapsd_max_sp_len;
ifmgd->p2p_noa_index = -1;
- mutex_init(&ifmgd->mtx);
-
if (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS)
ifmgd->req_smps = IEEE80211_SMPS_AUTOMATIC;
else
@@ -4053,8 +3971,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* try to authenticate/probe */
- mutex_lock(&ifmgd->mtx);
-
if ((ifmgd->auth_data && !ifmgd->auth_data->done) ||
ifmgd->assoc_data) {
err = -EBUSY;
@@ -4084,8 +4000,7 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
/* hold our own reference */
cfg80211_ref_bss(local->hw.wiphy, auth_data->bss);
- err = 0;
- goto out_unlock;
+ return 0;
err_clear:
memset(ifmgd->bssid, 0, ETH_ALEN);
@@ -4093,9 +4008,6 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
ifmgd->auth_data = NULL;
err_free:
kfree(auth_data);
- out_unlock:
- mutex_unlock(&ifmgd->mtx);
-
return err;
}
@@ -4126,8 +4038,6 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
assoc_data->ssid_len = ssidie[1];
rcu_read_unlock();
- mutex_lock(&ifmgd->mtx);
-
if (ifmgd->associated)
ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
@@ -4322,7 +4232,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
}
rcu_read_unlock();
- run_again(ifmgd, assoc_data->timeout);
+ run_again(sdata, assoc_data->timeout);
if (bss->corrupt_data) {
char *corrupt_type = "data";
@@ -4338,17 +4248,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
corrupt_type);
}
- err = 0;
- goto out;
+ return 0;
err_clear:
memset(ifmgd->bssid, 0, ETH_ALEN);
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
ifmgd->assoc_data = NULL;
err_free:
kfree(assoc_data);
- out:
- mutex_unlock(&ifmgd->mtx);
-
return err;
}
@@ -4360,8 +4266,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
bool tx = !req->local_state_change;
bool sent_frame = false;
- mutex_lock(&ifmgd->mtx);
-
sdata_info(sdata,
"deauthenticating from %pM by local choice (reason=%d)\n",
req->bssid, req->reason_code);
@@ -4373,7 +4277,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
req->reason_code, tx,
frame_buf);
ieee80211_destroy_auth_data(sdata, false);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
sent_frame = tx;
goto out;
@@ -4385,12 +4289,11 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
req->reason_code, tx, frame_buf);
sent_frame = tx;
}
- mutex_unlock(&ifmgd->mtx);
out:
if (sent_frame)
- __cfg80211_send_deauth(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
+ cfg80211_send_deauth(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
return 0;
}
@@ -4402,8 +4305,6 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
u8 bssid[ETH_ALEN];
u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
- mutex_lock(&ifmgd->mtx);
-
/*
* cfg80211 should catch this ... but it's racy since
* we can receive a disassoc frame, process it, hand it
@@ -4411,7 +4312,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
* trying to tell us that the user wants to disconnect.
*/
if (ifmgd->associated != req->bss) {
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
return -ENOLINK;
}
@@ -4423,10 +4324,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC,
req->reason_code, !req->local_state_change,
frame_buf);
- mutex_unlock(&ifmgd->mtx);
- __cfg80211_send_disassoc(sdata->dev, frame_buf,
- IEEE80211_DEAUTH_FRAME_LEN);
+ cfg80211_send_disassoc(sdata->dev, frame_buf,
+ IEEE80211_DEAUTH_FRAME_LEN);
return 0;
}
@@ -4446,13 +4346,13 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
cancel_work_sync(&ifmgd->csa_connection_drop_work);
cancel_work_sync(&ifmgd->chswitch_work);
- mutex_lock(&ifmgd->mtx);
+ sdata_lock(sdata);
if (ifmgd->assoc_data)
ieee80211_destroy_assoc_data(sdata, false);
if (ifmgd->auth_data)
ieee80211_destroy_auth_data(sdata, false);
del_timer_sync(&ifmgd->timer);
- mutex_unlock(&ifmgd->mtx);
+ sdata_unlock(sdata);
}
void ieee80211_cqm_rssi_notify(struct ieee80211_vif *vif,
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 27e0715..16366b3 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1607,9 +1607,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
if (sdata->u.mgd.dtim_period)
changed |= BSS_CHANGED_DTIM_PERIOD;
- mutex_lock(&sdata->u.mgd.mtx);
+ sdata_lock(sdata);
ieee80211_bss_info_change_notify(sdata, changed);
- mutex_unlock(&sdata->u.mgd.mtx);
+ sdata_unlock(sdata);
break;
case NL80211_IFTYPE_ADHOC:
changed |= BSS_CHANGED_IBSS;
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 2f9d20c..06e982d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -25,12 +25,9 @@ void cfg80211_send_rx_auth(struct net_device *dev, const u8 *buf, size_t len)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_rx_auth(dev);
- wdev_lock(wdev);
nl80211_send_rx_auth(rdev, dev, buf, len, GFP_KERNEL);
cfg80211_sme_rx_auth(dev, buf, len);
-
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_rx_auth);
@@ -46,7 +43,6 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
int ieoffs = offsetof(struct ieee80211_mgmt, u.assoc_resp.variable);
trace_cfg80211_send_rx_assoc(dev, bss);
- wdev_lock(wdev);
status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code);
@@ -59,7 +55,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
if (status_code != WLAN_STATUS_SUCCESS && wdev->conn &&
cfg80211_sme_failed_reassoc(wdev)) {
cfg80211_put_bss(wiphy, bss);
- goto out;
+ return;
}
nl80211_send_rx_assoc(rdev, dev, buf, len, GFP_KERNEL);
@@ -71,7 +67,7 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
* sme will schedule work that does it later.
*/
cfg80211_put_bss(wiphy, bss);
- goto out;
+ return;
}
if (!wdev->conn && wdev->sme_state == CFG80211_SME_IDLE) {
@@ -87,13 +83,11 @@ void cfg80211_send_rx_assoc(struct net_device *dev, struct cfg80211_bss *bss,
__cfg80211_connect_result(dev, mgmt->bssid, NULL, 0, ie, len - ieoffs,
status_code,
status_code == WLAN_STATUS_SUCCESS, bss);
- out:
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_rx_assoc);
-void __cfg80211_send_deauth(struct net_device *dev,
- const u8 *buf, size_t len)
+void cfg80211_send_deauth(struct net_device *dev,
+ const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -102,7 +96,7 @@ void __cfg80211_send_deauth(struct net_device *dev,
const u8 *bssid = mgmt->bssid;
bool was_current = false;
- trace___cfg80211_send_deauth(dev);
+ trace_cfg80211_send_deauth(dev);
ASSERT_WDEV_LOCK(wdev);
if (wdev->current_bss &&
@@ -129,20 +123,10 @@ void __cfg80211_send_deauth(struct net_device *dev,
false, NULL);
}
}
-EXPORT_SYMBOL(__cfg80211_send_deauth);
-
-void cfg80211_send_deauth(struct net_device *dev, const u8 *buf, size_t len)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
- wdev_lock(wdev);
- __cfg80211_send_deauth(dev, buf, len);
- wdev_unlock(wdev);
-}
EXPORT_SYMBOL(cfg80211_send_deauth);
-void __cfg80211_send_disassoc(struct net_device *dev,
- const u8 *buf, size_t len)
+void cfg80211_send_disassoc(struct net_device *dev,
+ const u8 *buf, size_t len)
{
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct wiphy *wiphy = wdev->wiphy;
@@ -152,7 +136,7 @@ void __cfg80211_send_disassoc(struct net_device *dev,
u16 reason_code;
bool from_ap;
- trace___cfg80211_send_disassoc(dev);
+ trace_cfg80211_send_disassoc(dev);
ASSERT_WDEV_LOCK(wdev);
nl80211_send_disassoc(rdev, dev, buf, len, GFP_KERNEL);
@@ -175,16 +159,6 @@ void __cfg80211_send_disassoc(struct net_device *dev,
from_ap = !ether_addr_equal(mgmt->sa, dev->dev_addr);
__cfg80211_disconnected(dev, NULL, 0, reason_code, from_ap);
}
-EXPORT_SYMBOL(__cfg80211_send_disassoc);
-
-void cfg80211_send_disassoc(struct net_device *dev, const u8 *buf, size_t len)
-{
- struct wireless_dev *wdev = dev->ieee80211_ptr;
-
- wdev_lock(wdev);
- __cfg80211_send_disassoc(dev, buf, len);
- wdev_unlock(wdev);
-}
EXPORT_SYMBOL(cfg80211_send_disassoc);
void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
@@ -194,15 +168,12 @@ void cfg80211_send_auth_timeout(struct net_device *dev, const u8 *addr)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_auth_timeout(dev, addr);
- wdev_lock(wdev);
nl80211_send_auth_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);
-
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_auth_timeout);
@@ -213,15 +184,12 @@ void cfg80211_send_assoc_timeout(struct net_device *dev, const u8 *addr)
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
trace_cfg80211_send_assoc_timeout(dev, addr);
- wdev_lock(wdev);
nl80211_send_assoc_timeout(rdev, dev, addr, GFP_KERNEL);
if (wdev->sme_state == CFG80211_SME_CONNECTING)
__cfg80211_connect_result(dev, addr, NULL, 0, NULL, 0,
WLAN_STATUS_UNSPECIFIED_FAILURE,
false, NULL);
-
- wdev_unlock(wdev);
}
EXPORT_SYMBOL(cfg80211_send_assoc_timeout);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index 5755bc1..23fafea 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1911,12 +1911,12 @@ TRACE_EVENT(cfg80211_send_rx_assoc,
NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG)
);
-DEFINE_EVENT(netdev_evt_only, __cfg80211_send_deauth,
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_deauth,
TP_PROTO(struct net_device *netdev),
TP_ARGS(netdev)
);
-DEFINE_EVENT(netdev_evt_only, __cfg80211_send_disassoc,
+DEFINE_EVENT(netdev_evt_only, cfg80211_send_disassoc,
TP_PROTO(struct net_device *netdev),
TP_ARGS(netdev)
);
--
1.8.0
^ permalink raw reply related
* [RFC 2/4] cfg80211: use atomic_t for wiphy counter
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
There's no need to lock, we can just use an atomic_t.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/core.c | 11 +++--------
1 file changed, 3 insertions(+), 8 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 4e0b52f..875d79a 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -289,7 +289,7 @@ static void cfg80211_event_work(struct work_struct *work)
struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
{
- static int wiphy_counter;
+ static atomic_t wiphy_counter = ATOMIC_INIT(0);
struct cfg80211_registered_device *rdev;
int alloc_size;
@@ -311,20 +311,15 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
rdev->ops = ops;
- mutex_lock(&cfg80211_mutex);
-
- rdev->wiphy_idx = wiphy_counter++;
+ rdev->wiphy_idx = atomic_inc_return(&wiphy_counter);
if (unlikely(rdev->wiphy_idx < 0)) {
- wiphy_counter--;
- mutex_unlock(&cfg80211_mutex);
/* ugh, wrapped! */
+ atomic_dec(&wiphy_counter);
kfree(rdev);
return NULL;
}
- mutex_unlock(&cfg80211_mutex);
-
/* give it a proper name */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
--
1.8.0
^ permalink raw reply related
* [RFC 1/4] cfg80211: move cfg80211_get_dev_from_ifindex under wext
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
The function is only used and needed by the wext code
for scanning, so move it there.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
net/wireless/core.c | 21 ---------------------
net/wireless/core.h | 4 ----
net/wireless/scan.c | 21 +++++++++++++++++++++
3 files changed, 21 insertions(+), 25 deletions(-)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 68f0c96..4e0b52f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -90,27 +90,6 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
-{
- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
- struct net_device *dev;
-
- mutex_lock(&cfg80211_mutex);
- dev = dev_get_by_index(net, ifindex);
- if (!dev)
- goto out;
- if (dev->ieee80211_ptr) {
- rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
- rdev = ERR_PTR(-ENODEV);
- dev_put(dev);
- out:
- mutex_unlock(&cfg80211_mutex);
- return rdev;
-}
-
/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
diff --git a/net/wireless/core.h b/net/wireless/core.h
index fd35dae..95b2907 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -164,10 +164,6 @@ int get_wiphy_idx(struct wiphy *wiphy);
/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
-/* identical to cfg80211_get_dev_from_info but only operate on ifindex */
-extern struct cfg80211_registered_device *
-cfg80211_get_dev_from_ifindex(struct net *net, int ifindex);
-
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net);
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index fd99ea4..2ce44a7 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1040,6 +1040,27 @@ void cfg80211_unlink_bss(struct wiphy *wiphy, struct cfg80211_bss *pub)
EXPORT_SYMBOL(cfg80211_unlink_bss);
#ifdef CONFIG_CFG80211_WEXT
+static struct cfg80211_registered_device *
+cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
+{
+ struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+ struct net_device *dev;
+
+ mutex_lock(&cfg80211_mutex);
+ dev = dev_get_by_index(net, ifindex);
+ if (!dev)
+ goto out;
+ if (dev->ieee80211_ptr) {
+ rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
+ mutex_lock(&rdev->mtx);
+ } else
+ rdev = ERR_PTR(-ENODEV);
+ dev_put(dev);
+ out:
+ mutex_unlock(&cfg80211_mutex);
+ return rdev;
+}
+
int cfg80211_wext_siwscan(struct net_device *dev,
struct iw_request_info *info,
union iwreq_data *wrqu, char *extra)
--
1.8.0
^ permalink raw reply related
* [RFC 0/4] cfg80211/mac80211: simplify locking
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb
I got a little fed up with all the locking, and decided to simplify.
This should still work, but I've only done some very simple tests.
I'm hoping it'll fix some of the weird corner cases that Ben and
others have found, which may be due to different locks in different
cases and things racing against each other ... I'm not convinced it
really will though, but hey, who knows :)
johannes
^ permalink raw reply
* [RFC 3/4] cfg80211: vastly simplify locking
From: Johannes Berg @ 2013-05-10 12:08 UTC (permalink / raw)
To: linux-wireless; +Cc: greearb, Johannes Berg
In-Reply-To: <1368187689-29706-1-git-send-email-johannes@sipsolutions.net>
From: Johannes Berg <johannes.berg@intel.com>
Virtually all code paths in cfg80211 already (need to) hold
the RTNL. As such, there's little point in having another
four mutexes for various parts of the code, they just cause
lock ordering issues (and much of the time, the RTNL and a
few of the others need thus be held.)
Simplify all this by getting rid of the extra four mutexes
and just use the RTNL throughout. Only a few code changes
were needed to do this and we can get rid of a work struct
for bonus points.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
include/net/cfg80211.h | 5 +-
net/wireless/core.c | 169 +++++++++---------------------------------
net/wireless/core.h | 32 +-------
net/wireless/debugfs.c | 4 +-
net/wireless/ibss.c | 10 +--
net/wireless/mesh.c | 2 -
net/wireless/mlme.c | 12 +--
net/wireless/nl80211.c | 178 +++++++++------------------------------------
net/wireless/reg.c | 36 +++------
net/wireless/scan.c | 42 +++++------
net/wireless/sme.c | 26 +------
net/wireless/util.c | 11 ---
net/wireless/wext-compat.c | 22 +-----
net/wireless/wext-sme.c | 18 -----
14 files changed, 120 insertions(+), 447 deletions(-)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 26e9113..085e5f7 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1255,6 +1255,7 @@ struct cfg80211_ssid {
* @scan_start: time (in jiffies) when the scan started
* @wdev: the wireless device to scan for
* @aborted: (internal) scan request was notified as aborted
+ * @notified: (internal) scan request was notified as done or aborted
* @no_cck: used to send probe requests at non CCK rate in 2GHz band
*/
struct cfg80211_scan_request {
@@ -1272,7 +1273,7 @@ struct cfg80211_scan_request {
/* internal */
struct wiphy *wiphy;
unsigned long scan_start;
- bool aborted;
+ bool aborted, notified;
bool no_cck;
/* keep last */
@@ -2872,8 +2873,6 @@ struct wireless_dev {
struct mutex mtx;
- struct work_struct cleanup_work;
-
bool use_4addr, p2p_started;
u8 address[ETH_ALEN] __aligned(sizeof(u16));
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 875d79a..3837326 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -36,12 +36,10 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("wireless configuration support");
MODULE_ALIAS_GENL_FAMILY(NL80211_GENL_NAME);
-/* RCU-protected (and cfg80211_mutex for writers) */
+/* RCU-protected (and RTNL for writers) */
LIST_HEAD(cfg80211_rdev_list);
int cfg80211_rdev_list_generation;
-DEFINE_MUTEX(cfg80211_mutex);
-
/* for debugfs */
static struct dentry *ieee80211_debugfs_dir;
@@ -53,12 +51,11 @@ module_param(cfg80211_disable_40mhz_24ghz, bool, 0644);
MODULE_PARM_DESC(cfg80211_disable_40mhz_24ghz,
"Disable 40MHz support in the 2.4GHz band");
-/* requires cfg80211_mutex to be held! */
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
{
struct cfg80211_registered_device *result = NULL, *rdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (rdev->wiphy_idx == wiphy_idx) {
@@ -77,12 +74,11 @@ int get_wiphy_idx(struct wiphy *wiphy)
return rdev->wiphy_idx;
}
-/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
{
struct cfg80211_registered_device *rdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
rdev = cfg80211_rdev_by_wiphy_idx(wiphy_idx);
if (!rdev)
@@ -90,14 +86,13 @@ struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx)
return &rdev->wiphy;
}
-/* requires cfg80211_mutex to be held */
int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
char *newname)
{
struct cfg80211_registered_device *rdev2;
int wiphy_idx, taken = -1, result, digits;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
/* prohibit calling the thing phy%d when %d is not its number */
sscanf(newname, PHY_NAME "%d%n", &wiphy_idx, &taken);
@@ -195,8 +190,7 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev)
{
- lockdep_assert_held(&rdev->devlist_mtx);
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
if (WARN_ON(wdev->iftype != NL80211_IFTYPE_P2P_DEVICE))
return;
@@ -235,8 +229,6 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
rtnl_lock();
- /* read-only iteration need not hold the devlist_mtx */
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->netdev) {
dev_close(wdev->netdev);
@@ -245,12 +237,7 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked)
/* otherwise, check iftype */
switch (wdev->iftype) {
case NL80211_IFTYPE_P2P_DEVICE:
- /* but this requires it */
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
break;
default:
break;
@@ -278,10 +265,7 @@ static void cfg80211_event_work(struct work_struct *work)
event_work);
rtnl_lock();
- cfg80211_lock_rdev(rdev);
-
cfg80211_process_rdev_events(rdev);
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -323,9 +307,6 @@ struct wiphy *wiphy_new(const struct cfg80211_ops *ops, int sizeof_priv)
/* give it a proper name */
dev_set_name(&rdev->wiphy.dev, PHY_NAME "%d", rdev->wiphy_idx);
- mutex_init(&rdev->mtx);
- mutex_init(&rdev->devlist_mtx);
- mutex_init(&rdev->sched_scan_mtx);
INIT_LIST_HEAD(&rdev->wdev_list);
INIT_LIST_HEAD(&rdev->beacon_registrations);
spin_lock_init(&rdev->beacon_registrations_lock);
@@ -573,11 +554,11 @@ int wiphy_register(struct wiphy *wiphy)
/* check and set up bitrates */
ieee80211_set_bitrate_flags(wiphy);
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
res = device_add(&rdev->wiphy.dev);
if (res) {
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
return res;
}
@@ -606,23 +587,19 @@ int wiphy_register(struct wiphy *wiphy)
}
cfg80211_debugfs_rdev_add(rdev);
- mutex_unlock(&cfg80211_mutex);
- /*
- * due to a locking dependency this has to be outside of the
- * cfg80211_mutex lock
- */
res = rfkill_register(rdev->rfkill);
if (res)
goto out_rm_dev;
- rtnl_lock();
rdev->wiphy.registered = true;
- rtnl_unlock();
- return 0;
+ res = 0;
+ goto out;
out_rm_dev:
device_del(&rdev->wiphy.dev);
+out:
+ rtnl_unlock();
return res;
}
EXPORT_SYMBOL(wiphy_register);
@@ -650,25 +627,19 @@ void wiphy_unregister(struct wiphy *wiphy)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
- rtnl_lock();
- rdev->wiphy.registered = false;
- rtnl_unlock();
-
- rfkill_unregister(rdev->rfkill);
-
- /* protect the device list */
- mutex_lock(&cfg80211_mutex);
-
wait_event(rdev->dev_wait, ({
int __count;
- mutex_lock(&rdev->devlist_mtx);
+ rtnl_lock();
__count = rdev->opencount;
- mutex_unlock(&rdev->devlist_mtx);
+ rtnl_unlock();
__count == 0; }));
- mutex_lock(&rdev->devlist_mtx);
+ rtnl_lock();
+ rdev->wiphy.registered = false;
+
+ rfkill_unregister(rdev->rfkill);
+
BUG_ON(!list_empty(&rdev->wdev_list));
- mutex_unlock(&rdev->devlist_mtx);
/*
* First remove the hardware from everywhere, this makes
@@ -679,20 +650,6 @@ void wiphy_unregister(struct wiphy *wiphy)
synchronize_rcu();
/*
- * Try to grab rdev->mtx. If a command is still in progress,
- * hopefully the driver will refuse it since it's tearing
- * down the device already. We wait for this command to complete
- * before unlinking the item from the list.
- * Note: as codified by the BUG_ON above we cannot get here if
- * a virtual interface is still present. Hence, we can only get
- * to lock contention here if userspace issues a command that
- * identified the hardware by wiphy index.
- */
- cfg80211_lock_rdev(rdev);
- /* nothing */
- cfg80211_unlock_rdev(rdev);
-
- /*
* If this device got a regulatory hint tell core its
* free to listen now to a new shiny device regulatory hint
*/
@@ -701,7 +658,7 @@ void wiphy_unregister(struct wiphy *wiphy)
cfg80211_rdev_list_generation++;
device_del(&rdev->wiphy.dev);
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
flush_work(&rdev->scan_done_wk);
cancel_work_sync(&rdev->conn_work);
@@ -719,9 +676,6 @@ void cfg80211_dev_free(struct cfg80211_registered_device *rdev)
struct cfg80211_internal_bss *scan, *tmp;
struct cfg80211_beacon_registration *reg, *treg;
rfkill_destroy(rdev->rfkill);
- mutex_destroy(&rdev->mtx);
- mutex_destroy(&rdev->devlist_mtx);
- mutex_destroy(&rdev->sched_scan_mtx);
list_for_each_entry_safe(reg, treg, &rdev->beacon_registrations, list) {
list_del(®->list);
kfree(reg);
@@ -746,36 +700,6 @@ void wiphy_rfkill_set_hw_state(struct wiphy *wiphy, bool blocked)
}
EXPORT_SYMBOL(wiphy_rfkill_set_hw_state);
-static void wdev_cleanup_work(struct work_struct *work)
-{
- struct wireless_dev *wdev;
- struct cfg80211_registered_device *rdev;
-
- wdev = container_of(work, struct wireless_dev, cleanup_work);
- rdev = wiphy_to_dev(wdev->wiphy);
-
- mutex_lock(&rdev->sched_scan_mtx);
-
- if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) {
- rdev->scan_req->aborted = true;
- ___cfg80211_scan_done(rdev, true);
- }
-
- if (WARN_ON(rdev->sched_scan_req &&
- rdev->sched_scan_req->dev == wdev->netdev)) {
- __cfg80211_stop_sched_scan(rdev, false);
- }
-
- mutex_unlock(&rdev->sched_scan_mtx);
-
- mutex_lock(&rdev->devlist_mtx);
- rdev->opencount--;
- mutex_unlock(&rdev->devlist_mtx);
- wake_up(&rdev->dev_wait);
-
- dev_put(wdev->netdev);
-}
-
void cfg80211_unregister_wdev(struct wireless_dev *wdev)
{
struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
@@ -785,8 +709,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
if (WARN_ON(wdev->netdev))
return;
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
list_del_rcu(&wdev->list);
rdev->devlist_generation++;
@@ -798,8 +720,6 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev)
WARN_ON_ONCE(1);
break;
}
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
}
EXPORT_SYMBOL(cfg80211_unregister_wdev);
@@ -818,7 +738,7 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
}
void cfg80211_leave(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev)
+ struct wireless_dev *wdev)
{
struct net_device *dev = wdev->netdev;
@@ -828,9 +748,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
break;
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_STATION:
- mutex_lock(&rdev->sched_scan_mtx);
__cfg80211_stop_sched_scan(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
#ifdef CONFIG_CFG80211_WEXT
@@ -884,13 +802,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* are added with nl80211.
*/
mutex_init(&wdev->mtx);
- INIT_WORK(&wdev->cleanup_work, wdev_cleanup_work);
INIT_LIST_HEAD(&wdev->event_list);
spin_lock_init(&wdev->event_lock);
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
- mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
@@ -903,7 +819,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
}
wdev->netdev = dev;
wdev->sme_state = CFG80211_SME_IDLE;
- mutex_unlock(&rdev->devlist_mtx);
#ifdef CONFIG_CFG80211_WEXT
wdev->wext.default_key = -1;
wdev->wext.default_mgmt_key = -1;
@@ -929,26 +844,22 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_DOWN:
cfg80211_update_iface_num(rdev, wdev->iftype, -1);
- dev_hold(dev);
- queue_work(cfg80211_wq, &wdev->cleanup_work);
+ if (rdev->scan_req && rdev->scan_req->wdev == wdev) {
+ if (WARN_ON(!rdev->scan_req->notified))
+ rdev->scan_req->aborted = true;
+ ___cfg80211_scan_done(rdev, true);
+ }
+
+ if (WARN_ON(rdev->sched_scan_req &&
+ rdev->sched_scan_req->dev == wdev->netdev)) {
+ __cfg80211_stop_sched_scan(rdev, false);
+ }
+
+ rdev->opencount--;
+ wake_up(&rdev->dev_wait);
break;
case NETDEV_UP:
- /*
- * If we have a really quick DOWN/UP succession we may
- * have this work still pending ... cancel it and see
- * if it was pending, in which case we need to account
- * for some of the work it would have done.
- */
- if (cancel_work_sync(&wdev->cleanup_work)) {
- mutex_lock(&rdev->devlist_mtx);
- rdev->opencount--;
- mutex_unlock(&rdev->devlist_mtx);
- dev_put(dev);
- }
cfg80211_update_iface_num(rdev, wdev->iftype, 1);
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
switch (wdev->iftype) {
#ifdef CONFIG_CFG80211_WEXT
@@ -980,10 +891,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
}
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
rdev->opencount++;
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
/*
* Configure power management to the driver here so that its
@@ -1000,12 +908,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_UNREGISTER:
/*
- * NB: cannot take rdev->mtx here because this may be
- * called within code protected by it when interfaces
- * are removed with nl80211.
- */
- mutex_lock(&rdev->devlist_mtx);
- /*
* It is possible to get NETDEV_UNREGISTER
* multiple times. To detect that, check
* that the interface is still on the list
@@ -1021,7 +923,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
kfree(wdev->wext.keys);
#endif
}
- mutex_unlock(&rdev->devlist_mtx);
/*
* synchronise (so that we won't find this netdev
* from other code any more) and then clear the list
@@ -1041,9 +942,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
return notifier_from_errno(-EOPNOTSUPP);
if (rfkill_blocked(rdev->rfkill))
return notifier_from_errno(-ERFKILL);
- mutex_lock(&rdev->devlist_mtx);
ret = cfg80211_can_add_interface(rdev, wdev->iftype);
- mutex_unlock(&rdev->devlist_mtx);
if (ret)
return notifier_from_errno(ret);
break;
@@ -1061,12 +960,10 @@ static void __net_exit cfg80211_pernet_exit(struct net *net)
struct cfg80211_registered_device *rdev;
rtnl_lock();
- mutex_lock(&cfg80211_mutex);
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (net_eq(wiphy_net(&rdev->wiphy), net))
WARN_ON(cfg80211_switch_netns(rdev, &init_net));
}
- mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
}
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 95b2907..d21a0fc 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -5,7 +5,6 @@
*/
#ifndef __NET_WIRELESS_CORE_H
#define __NET_WIRELESS_CORE_H
-#include <linux/mutex.h>
#include <linux/list.h>
#include <linux/netdevice.h>
#include <linux/rbtree.h>
@@ -23,11 +22,6 @@
struct cfg80211_registered_device {
const struct cfg80211_ops *ops;
struct list_head list;
- /* we hold this mutex during any call so that
- * we cannot do multiple calls at once, and also
- * to avoid the deregister call to proceed while
- * any call is in progress */
- struct mutex mtx;
/* rfkill support */
struct rfkill_ops rfkill_ops;
@@ -49,9 +43,7 @@ struct cfg80211_registered_device {
/* wiphy index, internal only */
int wiphy_idx;
- /* associated wireless interfaces */
- struct mutex devlist_mtx;
- /* protected by devlist_mtx or RCU */
+ /* associated wireless interfaces, protected by rtnl or RCU */
struct list_head wdev_list;
int devlist_generation, wdev_id;
int opencount; /* also protected by devlist_mtx */
@@ -75,8 +67,6 @@ struct cfg80211_registered_device {
struct work_struct scan_done_wk;
struct work_struct sched_scan_results_wk;
- struct mutex sched_scan_mtx;
-
#ifdef CONFIG_NL80211_TESTMODE
struct genl_info *testmode_info;
#endif
@@ -120,15 +110,9 @@ cfg80211_rdev_free_wowlan(struct cfg80211_registered_device *rdev)
}
extern struct workqueue_struct *cfg80211_wq;
-extern struct mutex cfg80211_mutex;
extern struct list_head cfg80211_rdev_list;
extern int cfg80211_rdev_list_generation;
-static inline void assert_cfg80211_lock(void)
-{
- lockdep_assert_held(&cfg80211_mutex);
-}
-
struct cfg80211_internal_bss {
struct list_head list;
struct list_head hidden_list;
@@ -161,23 +145,11 @@ static inline void cfg80211_unhold_bss(struct cfg80211_internal_bss *bss)
struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx);
int get_wiphy_idx(struct wiphy *wiphy);
-/* requires cfg80211_rdev_mutex to be held! */
struct wiphy *wiphy_idx_to_wiphy(int wiphy_idx);
int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
struct net *net);
-static inline void cfg80211_lock_rdev(struct cfg80211_registered_device *rdev)
-{
- mutex_lock(&rdev->mtx);
-}
-
-static inline void cfg80211_unlock_rdev(struct cfg80211_registered_device *rdev)
-{
- BUG_ON(IS_ERR(rdev) || !rdev);
- mutex_unlock(&rdev->mtx);
-}
-
static inline void wdev_lock(struct wireless_dev *wdev)
__acquires(wdev)
{
@@ -192,7 +164,7 @@ static inline void wdev_unlock(struct wireless_dev *wdev)
mutex_unlock(&wdev->mtx);
}
-#define ASSERT_RDEV_LOCK(rdev) lockdep_assert_held(&(rdev)->mtx)
+#define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL()
#define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx)
static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev)
diff --git a/net/wireless/debugfs.c b/net/wireless/debugfs.c
index 920cabe..90d0500 100644
--- a/net/wireless/debugfs.c
+++ b/net/wireless/debugfs.c
@@ -74,7 +74,7 @@ static ssize_t ht40allow_map_read(struct file *file,
if (!buf)
return -ENOMEM;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
sband = wiphy->bands[band];
@@ -85,7 +85,7 @@ static ssize_t ht40allow_map_read(struct file *file,
buf, buf_size, offset);
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
r = simple_read_from_buffer(user_buf, count, ppos, buf, offset);
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index d80e471..5449c5a 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -152,11 +152,11 @@ int cfg80211_join_ibss(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(wdev);
err = __cfg80211_join_ibss(rdev, dev, params, connkeys);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -359,11 +359,9 @@ int cfg80211_ibss_wext_siwfreq(struct net_device *dev,
wdev->wext.ibss.channel_fixed = false;
}
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -429,11 +427,9 @@ int cfg80211_ibss_wext_siwessid(struct net_device *dev,
memcpy(wdev->wext.ibss.ssid, ssid, len);
wdev->wext.ibss.ssid_len = len;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -512,11 +508,9 @@ int cfg80211_ibss_wext_siwap(struct net_device *dev,
} else
wdev->wext.ibss.bssid = NULL;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = cfg80211_ibss_wext_join(rdev, wdev);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c
index 0bb93f3..6c216ad 100644
--- a/net/wireless/mesh.c
+++ b/net/wireless/mesh.c
@@ -185,11 +185,9 @@ int cfg80211_join_mesh(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(wdev);
err = __cfg80211_join_mesh(rdev, dev, setup, conf);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 0c7b7dd..2f9d20c 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -314,14 +314,14 @@ int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev,
{
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_mlme_auth(rdev, dev, chan, auth_type, bssid,
ssid, ssid_len, ie, ie_len,
key, key_len, key_idx,
sae_data, sae_data_len);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -425,12 +425,12 @@ int cfg80211_mlme_assoc(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
int err;
- mutex_lock(&rdev->devlist_mtx);
+ ASSERT_RTNL();
+
wdev_lock(wdev);
err = __cfg80211_mlme_assoc(rdev, dev, chan, bssid,
ssid, ssid_len, req);
wdev_unlock(wdev);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -848,7 +848,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
dfs_update_channels_wk);
wiphy = &rdev->wiphy;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
for (bandid = 0; bandid < IEEE80211_NUM_BANDS; bandid++) {
sband = wiphy->bands[bandid];
if (!sband)
@@ -881,7 +881,7 @@ void cfg80211_dfs_channels_update_work(struct work_struct *work)
check_again = true;
}
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
/* reschedule if there are other channels waiting to be cleared again */
if (check_again)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9cdcd9e..74cef32 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -59,7 +59,7 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
int wiphy_idx = -1;
int ifidx = -1;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
if (!have_ifidx && !have_wdev_id)
return ERR_PTR(-EINVAL);
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
continue;
- mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (have_ifidx && wdev->netdev &&
wdev->netdev->ifindex == ifidx) {
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
break;
}
}
- mutex_unlock(&rdev->devlist_mtx);
if (result)
break;
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
struct cfg80211_registered_device *rdev = NULL, *tmp;
struct net_device *netdev;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
if (!attrs[NL80211_ATTR_WIPHY] &&
!attrs[NL80211_ATTR_IFINDEX] &&
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
if (tmp) {
/* make sure wdev exists */
- mutex_lock(&tmp->devlist_mtx);
list_for_each_entry(wdev, &tmp->wdev_list, list) {
if (wdev->identifier != (u32)wdev_id)
continue;
found = true;
break;
}
- mutex_unlock(&tmp->devlist_mtx);
if (!found)
tmp = NULL;
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
/*
* This function returns a pointer to the driver
* that the genl_info item that is passed refers to.
- * If successful, it returns non-NULL and also locks
- * the driver's mutex!
- *
- * This means that you need to call cfg80211_unlock_rdev()
- * before being allowed to acquire &cfg80211_mutex!
- *
- * This is necessary because we need to lock the global
- * mutex to get an item off the list safely, and then
- * we lock the rdev mutex so it doesn't go away under us.
- *
- * We don't want to keep cfg80211_mutex locked
- * for all the time in order to allow requests on
- * other interfaces to go through at the same time.
*
* The result of this can be a PTR_ERR and hence must
* be checked with IS_ERR() for errors.
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
static struct cfg80211_registered_device *
cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
{
- struct cfg80211_registered_device *rdev;
-
- mutex_lock(&cfg80211_mutex);
- rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
-
- /* if it is not an error we grab the lock on
- * it to assure it won't be going away while
- * we operate on it */
- if (!IS_ERR(rdev))
- mutex_lock(&rdev->mtx);
-
- mutex_unlock(&cfg80211_mutex);
-
- return rdev;
+ return __cfg80211_rdev_from_attrs(netns, info->attrs);
}
/* policy for the attributes */
@@ -455,7 +425,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
int err;
rtnl_lock();
- mutex_lock(&cfg80211_mutex);
if (!cb->args[0]) {
err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
@@ -484,14 +453,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
*rdev = wiphy_to_dev(wiphy);
*wdev = NULL;
- mutex_lock(&(*rdev)->devlist_mtx);
list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
if (tmp->identifier == cb->args[1]) {
*wdev = tmp;
break;
}
}
- mutex_unlock(&(*rdev)->devlist_mtx);
if (!*wdev) {
err = -ENODEV;
@@ -499,19 +466,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
}
}
- cfg80211_lock_rdev(*rdev);
-
- mutex_unlock(&cfg80211_mutex);
return 0;
out_unlock:
- mutex_unlock(&cfg80211_mutex);
rtnl_unlock();
return err;
}
static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
{
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -1567,7 +1529,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
struct nlattr **tb = nl80211_fam.attrbuf;
int res;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
tb, nl80211_fam.maxattr, nl80211_policy);
if (res == 0) {
@@ -1581,10 +1543,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
- if (!netdev) {
- mutex_unlock(&cfg80211_mutex);
+ if (!netdev)
return -ENODEV;
- }
if (netdev->ieee80211_ptr) {
dev = wiphy_to_dev(
netdev->ieee80211_ptr->wiphy);
@@ -1628,7 +1588,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
!skb->len &&
cb->min_dump_alloc < 4096) {
cb->min_dump_alloc = 4096;
- mutex_unlock(&cfg80211_mutex);
return 1;
}
idx--;
@@ -1637,7 +1596,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
} while (cb->args[1] > 0);
break;
}
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
cb->args[0] = idx;
@@ -1792,7 +1751,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
if (result)
return result;
- mutex_lock(&rdev->devlist_mtx);
switch (iftype) {
case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_P2P_GO:
@@ -1816,7 +1774,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
default:
result = -EINVAL;
}
- mutex_unlock(&rdev->devlist_mtx);
return result;
}
@@ -1865,6 +1822,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u32 frag_threshold = 0, rts_threshold = 0;
u8 coverage_class = 0;
+ ASSERT_RTNL();
+
/*
* Try to find the wiphy and netdev. Normally this
* function shouldn't need the netdev, but this is
@@ -1874,31 +1833,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
* also passed a netdev to set_wiphy, so that it is
* possible to let that go to the right netdev!
*/
- mutex_lock(&cfg80211_mutex);
if (info->attrs[NL80211_ATTR_IFINDEX]) {
int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
netdev = dev_get_by_index(genl_info_net(info), ifindex);
- if (netdev && netdev->ieee80211_ptr) {
+ if (netdev && netdev->ieee80211_ptr)
rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
+ else
netdev = NULL;
}
if (!netdev) {
rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
info->attrs);
- if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
+ if (IS_ERR(rdev))
return PTR_ERR(rdev);
- }
wdev = NULL;
netdev = NULL;
result = 0;
-
- mutex_lock(&rdev->mtx);
} else
wdev = netdev->ieee80211_ptr;
@@ -1911,8 +1864,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = cfg80211_dev_rename(
rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
- mutex_unlock(&cfg80211_mutex);
-
if (result)
goto bad_res;
@@ -2119,7 +2070,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
bad_res:
- mutex_unlock(&rdev->mtx);
if (netdev)
dev_put(netdev);
return result;
@@ -2217,7 +2167,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
continue;
@@ -2227,7 +2177,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
}
if_idx = 0;
- mutex_lock(&rdev->devlist_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (if_idx < if_start) {
if_idx++;
@@ -2236,17 +2185,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev) < 0) {
- mutex_unlock(&rdev->devlist_mtx);
goto out;
}
if_idx++;
}
- mutex_unlock(&rdev->devlist_mtx);
wp_idx++;
}
out:
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
cb->args[0] = wp_idx;
cb->args[1] = if_idx;
@@ -2479,11 +2426,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
INIT_LIST_HEAD(&wdev->mgmt_registrations);
spin_lock_init(&wdev->mgmt_registrations_lock);
- mutex_lock(&rdev->devlist_mtx);
wdev->identifier = ++rdev->wdev_id;
list_add_rcu(&wdev->list, &rdev->wdev_list);
rdev->devlist_generation++;
- mutex_unlock(&rdev->devlist_mtx);
break;
default:
break;
@@ -2992,8 +2937,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
struct wireless_dev *wdev;
bool ret = false;
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (wdev->iftype != NL80211_IFTYPE_AP &&
wdev->iftype != NL80211_IFTYPE_P2P_GO)
@@ -3007,8 +2950,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
break;
}
- mutex_unlock(&rdev->devlist_mtx);
-
return ret;
}
@@ -3170,13 +3111,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
params.radar_required = true;
}
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
params.chandef.chan,
CHAN_MODE_SHARED,
radar_detect_width);
- mutex_unlock(&rdev->devlist_mtx);
-
if (err)
return err;
@@ -4899,18 +4837,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
void *hdr = NULL;
struct nlattr *nl_reg_rules;
unsigned int i;
- int err = -EINVAL;
-
- mutex_lock(&cfg80211_mutex);
if (!cfg80211_regdomain)
- goto out;
+ return -EINVAL;
msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
- if (!msg) {
- err = -ENOBUFS;
- goto out;
- }
+ if (!msg)
+ return -ENOBUFS;
hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
NL80211_CMD_GET_REG);
@@ -4969,8 +4902,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
nla_nest_end(msg, nl_reg_rules);
genlmsg_end(msg, hdr);
- err = genlmsg_reply(msg, info);
- goto out;
+ return genlmsg_reply(msg, info);
nla_put_failure_rcu:
rcu_read_unlock();
@@ -4978,10 +4910,7 @@ nla_put_failure:
genlmsg_cancel(msg, hdr);
put_failure:
nlmsg_free(msg);
- err = -EMSGSIZE;
-out:
- mutex_unlock(&cfg80211_mutex);
- return err;
+ return -EMSGSIZE;
}
static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
@@ -5047,12 +4976,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
}
}
- mutex_lock(&cfg80211_mutex);
-
r = set_regdom(rd);
/* set_regdom took ownership */
rd = NULL;
- mutex_unlock(&cfg80211_mutex);
bad_reg:
kfree(rd);
@@ -5102,7 +5028,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->scan)
return -EOPNOTSUPP;
- mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) {
err = -EBUSY;
goto unlock;
@@ -5288,7 +5213,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
}
unlock:
- mutex_unlock(&rdev->sched_scan_mtx);
return err;
}
@@ -5360,8 +5284,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
if (ie_len > wiphy->max_sched_scan_ie_len)
return -EINVAL;
- mutex_lock(&rdev->sched_scan_mtx);
-
if (rdev->sched_scan_req) {
err = -EINPROGRESS;
goto out;
@@ -5529,7 +5451,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
out_free:
kfree(request);
out:
- mutex_unlock(&rdev->sched_scan_mtx);
return err;
}
@@ -5537,17 +5458,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- int err;
if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
!rdev->ops->sched_scan_stop)
return -EOPNOTSUPP;
- mutex_lock(&rdev->sched_scan_mtx);
- err = __cfg80211_stop_sched_scan(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
-
- return err;
+ return __cfg80211_stop_sched_scan(rdev, false);
}
static int nl80211_start_radar_detection(struct sk_buff *skb,
@@ -5579,12 +5495,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
if (!rdev->ops->start_radar_detection)
return -EOPNOTSUPP;
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
chandef.chan, CHAN_MODE_SHARED,
BIT(chandef.width));
if (err)
- goto err_locked;
+ return err;
err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
if (!err) {
@@ -5592,9 +5507,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
wdev->cac_started = true;
wdev->cac_start_time = jiffies;
}
-err_locked:
- mutex_unlock(&rdev->devlist_mtx);
-
return err;
}
@@ -6457,6 +6369,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
void *data = NULL;
int data_len = 0;
+ rtnl_lock();
+
if (cb->args[0]) {
/*
* 0 is a valid index, but not valid for args[0],
@@ -6468,18 +6382,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
nl80211_fam.attrbuf, nl80211_fam.maxattr,
nl80211_policy);
if (err)
- return err;
+ goto out_err;
- mutex_lock(&cfg80211_mutex);
rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
nl80211_fam.attrbuf);
if (IS_ERR(rdev)) {
- mutex_unlock(&cfg80211_mutex);
- return PTR_ERR(rdev);
+ err = PTR_ERR(rdev);
+ goto out_err;
}
phy_idx = rdev->wiphy_idx;
rdev = NULL;
- mutex_unlock(&cfg80211_mutex);
if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
cb->args[1] =
@@ -6491,14 +6403,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
data_len = nla_len((void *)cb->args[1]);
}
- mutex_lock(&cfg80211_mutex);
rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
if (!rdev) {
- mutex_unlock(&cfg80211_mutex);
- return -ENOENT;
+ err = -ENOENT;
+ goto out_err;
}
- cfg80211_lock_rdev(rdev);
- mutex_unlock(&cfg80211_mutex);
if (!rdev->ops->testmode_dump) {
err = -EOPNOTSUPP;
@@ -6539,7 +6448,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
/* see above */
cb->args[0] = phy_idx + 1;
out_err:
- cfg80211_unlock_rdev(rdev);
+ rtnl_unlock();
return err;
}
@@ -8172,9 +8081,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (wdev->p2p_started)
return 0;
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_add_interface(rdev, wdev->iftype);
- mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -8183,9 +8090,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
return err;
wdev->p2p_started = true;
- mutex_lock(&rdev->devlist_mtx);
rdev->opencount++;
- mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8201,11 +8106,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
if (!rdev->ops->stop_p2p_device)
return -EOPNOTSUPP;
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
cfg80211_stop_p2p_device(rdev, wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
return 0;
}
@@ -8348,11 +8249,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
info->user_ptr[0] = rdev;
} else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
info->attrs);
if (IS_ERR(wdev)) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return PTR_ERR(wdev);
@@ -8363,7 +8264,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
if (!dev) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -EINVAL;
@@ -8377,7 +8277,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
if (dev) {
if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
!netif_running(dev)) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
@@ -8386,17 +8285,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
dev_hold(dev);
} else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
if (!wdev->p2p_started) {
- mutex_unlock(&cfg80211_mutex);
if (rtnl)
rtnl_unlock();
return -ENETDOWN;
}
}
- cfg80211_lock_rdev(rdev);
-
- mutex_unlock(&cfg80211_mutex);
-
info->user_ptr[0] = rdev;
}
@@ -8406,8 +8300,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
struct genl_info *info)
{
- if (info->user_ptr[0])
- cfg80211_unlock_rdev(info->user_ptr[0]);
if (info->user_ptr[1]) {
if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
struct wireless_dev *wdev = info->user_ptr[1];
@@ -8429,7 +8321,8 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_wiphy,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WIPHY,
+ .internal_flags = NL80211_FLAG_NEED_WIPHY |
+ NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_WIPHY,
@@ -8444,7 +8337,8 @@ static struct genl_ops nl80211_ops[] = {
.dumpit = nl80211_dump_interface,
.policy = nl80211_policy,
/* can be retrieved by unprivileged users */
- .internal_flags = NL80211_FLAG_NEED_WDEV,
+ .internal_flags = NL80211_FLAG_NEED_WDEV |
+ NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_SET_INTERFACE,
@@ -8603,6 +8497,7 @@ static struct genl_ops nl80211_ops[] = {
.cmd = NL80211_CMD_GET_REG,
.doit = nl80211_get_reg,
.policy = nl80211_policy,
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
/* can be retrieved by unprivileged users */
},
{
@@ -8610,6 +8505,7 @@ static struct genl_ops nl80211_ops[] = {
.doit = nl80211_set_reg,
.policy = nl80211_policy,
.flags = GENL_ADMIN_PERM,
+ .internal_flags = NL80211_FLAG_NEED_RTNL,
},
{
.cmd = NL80211_CMD_REQ_SET_REG,
@@ -9065,8 +8961,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
struct nlattr *nest;
int i;
- lockdep_assert_held(&rdev->sched_scan_mtx);
-
if (WARN_ON(!req))
return 0;
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index e713051..5ceadbb 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -387,7 +387,7 @@ static void reg_regdb_search(struct work_struct *work)
const struct ieee80211_regdomain *curdom, *regdom = NULL;
int i;
- mutex_lock(&cfg80211_mutex);
+ rtnl_lock();
mutex_lock(®_regdb_search_mutex);
while (!list_empty(®_regdb_search_list)) {
@@ -412,7 +412,7 @@ static void reg_regdb_search(struct work_struct *work)
if (!IS_ERR_OR_NULL(regdom))
set_regdom(regdom);
- mutex_unlock(&cfg80211_mutex);
+ rtnl_unlock();
}
static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
@@ -1235,7 +1235,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
struct cfg80211_registered_device *rdev;
struct wiphy *wiphy;
- assert_cfg80211_lock();
+ ASSERT_RTNL();
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
wiphy = &rdev->wiphy;
@@ -1580,21 +1580,19 @@ static void reg_process_pending_hints(void)
{
struct regulatory_request *reg_request, *lr;
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
lr = get_last_request();
/* When last_request->processed becomes true this will be rescheduled */
if (lr && !lr->processed) {
REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
- goto out;
+ return;
}
spin_lock(®_requests_lock);
if (list_empty(®_requests_list)) {
spin_unlock(®_requests_lock);
- goto out;
+ return;
}
reg_request = list_first_entry(®_requests_list,
@@ -1605,10 +1603,6 @@ static void reg_process_pending_hints(void)
spin_unlock(®_requests_lock);
reg_process_hint(reg_request, reg_request->initiator);
-
-out:
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
}
/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1617,9 +1611,6 @@ static void reg_process_pending_beacon_hints(void)
struct cfg80211_registered_device *rdev;
struct reg_beacon *pending_beacon, *tmp;
- mutex_lock(&cfg80211_mutex);
- mutex_lock(®_mutex);
-
/* This goes through the _pending_ beacon list */
spin_lock_bh(®_pending_beacons_lock);
@@ -1636,14 +1627,16 @@ static void reg_process_pending_beacon_hints(void)
}
spin_unlock_bh(®_pending_beacons_lock);
- mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
}
static void reg_todo(struct work_struct *work)
{
+ rtnl_lock();
+ mutex_lock(®_mutex);
reg_process_pending_hints();
reg_process_pending_beacon_hints();
+ mutex_unlock(®_mutex);
+ rtnl_unlock();
}
static void queue_regulatory_request(struct regulatory_request *request)
@@ -1727,10 +1720,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
}
EXPORT_SYMBOL(regulatory_hint);
-/*
- * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
- * therefore cannot iterate over the rdev list here.
- */
void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
const u8 *country_ie, u8 country_ie_len)
{
@@ -1762,7 +1751,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
/*
* We will run this only upon a successful connection on cfg80211.
* We leave conflict resolution to the workqueue, where can hold
- * cfg80211_mutex.
+ * the RTNL.
*/
if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
lr->wiphy_idx != WIPHY_IDX_INVALID)
@@ -1868,7 +1857,8 @@ static void restore_regulatory_settings(bool reset_user)
LIST_HEAD(tmp_reg_req_list);
struct cfg80211_registered_device *rdev;
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
mutex_lock(®_mutex);
reset_regdomains(true, &world_regdom);
@@ -1925,7 +1915,6 @@ static void restore_regulatory_settings(bool reset_user)
spin_unlock(®_requests_lock);
mutex_unlock(®_mutex);
- mutex_unlock(&cfg80211_mutex);
REG_DBG_PRINT("Kicking the queue\n");
@@ -2307,7 +2296,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
mutex_unlock(®_mutex);
}
-/* Caller must hold cfg80211_mutex */
void wiphy_regulatory_deregister(struct wiphy *wiphy)
{
struct wiphy *request_wiphy = NULL;
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2ce44a7..dd01b58 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)
union iwreq_data wrqu;
#endif
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
request = rdev->scan_req;
@@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
scan_done_wk);
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
___cfg80211_scan_done(rdev, false);
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
@@ -241,6 +241,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
request->aborted = aborted;
+ request->notified = true;
queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
}
EXPORT_SYMBOL(cfg80211_scan_done);
@@ -255,7 +256,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
request = rdev->sched_scan_req;
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
/* we don't have sched_scan_req anymore if the scan is stopping */
if (request) {
@@ -270,7 +271,7 @@ void __cfg80211_sched_scan_results(struct work_struct *wk)
nl80211_send_sched_scan_results(rdev, request->dev);
}
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
void cfg80211_sched_scan_results(struct wiphy *wiphy)
@@ -289,9 +290,9 @@ void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
trace_cfg80211_sched_scan_stopped(wiphy);
- mutex_lock(&rdev->sched_scan_mtx);
+ rtnl_lock();
__cfg80211_stop_sched_scan(rdev, true);
- mutex_unlock(&rdev->sched_scan_mtx);
+ rtnl_unlock();
}
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
@@ -300,7 +301,7 @@ int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev,
{
struct net_device *dev;
- lockdep_assert_held(&rdev->sched_scan_mtx);
+ ASSERT_RTNL();
if (!rdev->sched_scan_req)
return -ENOENT;
@@ -1043,21 +1044,19 @@ EXPORT_SYMBOL(cfg80211_unlink_bss);
static struct cfg80211_registered_device *
cfg80211_get_dev_from_ifindex(struct net *net, int ifindex)
{
- struct cfg80211_registered_device *rdev = ERR_PTR(-ENODEV);
+ struct cfg80211_registered_device *rdev;
struct net_device *dev;
- mutex_lock(&cfg80211_mutex);
+ ASSERT_RTNL();
+
dev = dev_get_by_index(net, ifindex);
if (!dev)
- goto out;
- if (dev->ieee80211_ptr) {
+ return ERR_PTR(-ENODEV);
+ if (dev->ieee80211_ptr)
rdev = wiphy_to_dev(dev->ieee80211_ptr->wiphy);
- mutex_lock(&rdev->mtx);
- } else
+ else
rdev = ERR_PTR(-ENODEV);
dev_put(dev);
- out:
- mutex_unlock(&cfg80211_mutex);
return rdev;
}
@@ -1083,7 +1082,6 @@ int cfg80211_wext_siwscan(struct net_device *dev,
if (IS_ERR(rdev))
return PTR_ERR(rdev);
- mutex_lock(&rdev->sched_scan_mtx);
if (rdev->scan_req) {
err = -EBUSY;
goto out;
@@ -1190,9 +1188,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,
dev_hold(dev);
}
out:
- mutex_unlock(&rdev->sched_scan_mtx);
kfree(creq);
- cfg80211_unlock_rdev(rdev);
return err;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwscan);
@@ -1491,10 +1487,8 @@ int cfg80211_wext_giwscan(struct net_device *dev,
if (IS_ERR(rdev))
return PTR_ERR(rdev);
- if (rdev->scan_req) {
- res = -EAGAIN;
- goto out;
- }
+ if (rdev->scan_req)
+ return -EAGAIN;
res = ieee80211_scan_results(rdev, info, extra, data->length);
data->length = 0;
@@ -1503,8 +1497,6 @@ int cfg80211_wext_giwscan(struct net_device *dev,
res = 0;
}
- out:
- cfg80211_unlock_rdev(rdev);
return res;
}
EXPORT_SYMBOL_GPL(cfg80211_wext_giwscan);
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index a9dc5c7..4a6d7af 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -43,35 +43,29 @@ static bool cfg80211_is_all_idle(void)
struct wireless_dev *wdev;
bool is_all_idle = true;
- mutex_lock(&cfg80211_mutex);
-
/*
* All devices must be idle as otherwise if you are actively
* scanning some new beacon hints could be learned and would
* count as new regulatory hints.
*/
list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
- cfg80211_lock_rdev(rdev);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE)
is_all_idle = false;
wdev_unlock(wdev);
}
- cfg80211_unlock_rdev(rdev);
}
- mutex_unlock(&cfg80211_mutex);
-
return is_all_idle;
}
static void disconnect_work(struct work_struct *work)
{
- if (!cfg80211_is_all_idle())
- return;
-
- regulatory_hint_disconnect();
+ rtnl_lock();
+ if (cfg80211_is_all_idle())
+ regulatory_hint_disconnect();
+ rtnl_unlock();
}
static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
@@ -85,7 +79,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev);
ASSERT_WDEV_LOCK(wdev);
- lockdep_assert_held(&rdev->sched_scan_mtx);
if (rdev->scan_req)
return -EBUSY;
@@ -226,9 +219,6 @@ void cfg80211_conn_work(struct work_struct *work)
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
rtnl_lock();
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
list_for_each_entry(wdev, &rdev->wdev_list, list) {
wdev_lock(wdev);
@@ -253,9 +243,6 @@ void cfg80211_conn_work(struct work_struct *work)
wdev_unlock(wdev);
}
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
rtnl_unlock();
}
@@ -928,14 +915,9 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
{
int err;
- mutex_lock(&rdev->devlist_mtx);
- /* might request scan - scan_mtx -> wdev_mtx dependency */
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_connect(rdev, dev, connect, connkeys, NULL);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
diff --git a/net/wireless/util.c b/net/wireless/util.c
index bb52486..0be3f0d 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -785,12 +785,8 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev)
ASSERT_RTNL();
ASSERT_RDEV_LOCK(rdev);
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list)
cfg80211_process_wdev_events(wdev);
-
- mutex_unlock(&rdev->devlist_mtx);
}
int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
@@ -822,10 +818,8 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
return -EBUSY;
if (ntype != otype && netif_running(dev)) {
- mutex_lock(&rdev->devlist_mtx);
err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
ntype);
- mutex_unlock(&rdev->devlist_mtx);
if (err)
return err;
@@ -1187,8 +1181,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
if (!beacon_int)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
-
list_for_each_entry(wdev, &rdev->wdev_list, list) {
if (!wdev->beacon_interval)
continue;
@@ -1198,8 +1190,6 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
}
}
- mutex_unlock(&rdev->devlist_mtx);
-
return res;
}
@@ -1223,7 +1213,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
int i, j;
ASSERT_RTNL();
- lockdep_assert_held(&rdev->devlist_mtx);
if (WARN_ON(hweight32(radar_detect) > 1))
return -EINVAL;
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index d997d0f..e7c6e86 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -72,7 +72,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev;
struct vif_params vifparams;
enum nl80211_iftype type;
- int ret;
rdev = wiphy_to_dev(wdev->wiphy);
@@ -98,11 +97,7 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams));
- cfg80211_lock_rdev(rdev);
- ret = cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
- cfg80211_unlock_rdev(rdev);
-
- return ret;
+ return cfg80211_change_iface(rdev, dev, type, NULL, &vifparams);
}
EXPORT_SYMBOL_GPL(cfg80211_wext_siwmode);
@@ -579,13 +574,10 @@ static int cfg80211_set_encryption(struct cfg80211_registered_device *rdev,
{
int err;
- /* devlist mutex needed for possible IBSS re-join */
- mutex_lock(&rdev->devlist_mtx);
wdev_lock(dev->ieee80211_ptr);
err = __cfg80211_set_encryption(rdev, dev, pairwise, addr,
remove, tx_key, idx, params);
wdev_unlock(dev->ieee80211_ptr);
- mutex_unlock(&rdev->devlist_mtx);
return err;
}
@@ -787,7 +779,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
};
- int freq, err;
+ int freq;
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
@@ -804,10 +796,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_monitor_channel(rdev, &chandef);
- mutex_unlock(&rdev->devlist_mtx);
- return err;
+ return cfg80211_set_monitor_channel(rdev, &chandef);
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wdev->wiphy, wextfreq);
if (freq < 0)
@@ -818,10 +807,7 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
if (!chandef.chan)
return -EINVAL;
- mutex_lock(&rdev->devlist_mtx);
- err = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
- mutex_unlock(&rdev->devlist_mtx);
- return err;
+ return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
default:
return -EOPNOTSUPP;
}
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index e79cb5c..aeefd68 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -87,9 +87,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
return -EINVAL;
}
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -136,9 +133,6 @@ int cfg80211_mgd_wext_siwfreq(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
@@ -190,9 +184,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
if (len > 0 && ssid[len - 1] == '\0')
len--;
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
err = 0;
@@ -226,9 +217,6 @@ int cfg80211_mgd_wext_siwessid(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
@@ -287,9 +275,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid))
bssid = NULL;
- cfg80211_lock_rdev(rdev);
- mutex_lock(&rdev->devlist_mtx);
- mutex_lock(&rdev->sched_scan_mtx);
wdev_lock(wdev);
if (wdev->sme_state != CFG80211_SME_IDLE) {
@@ -318,9 +303,6 @@ int cfg80211_mgd_wext_siwap(struct net_device *dev,
err = cfg80211_mgd_wext_connect(rdev, wdev);
out:
wdev_unlock(wdev);
- mutex_unlock(&rdev->sched_scan_mtx);
- mutex_unlock(&rdev->devlist_mtx);
- cfg80211_unlock_rdev(rdev);
return err;
}
--
1.8.0
^ 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