diff options
author | Johannes Berg <johannes.berg@intel.com> | 2013-09-26 20:03:45 +0200 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2013-09-26 20:03:45 +0200 |
commit | aa5f66d5a1df1c2b04bccdcb19711675c765d7c4 (patch) | |
tree | e1de25f7c9a1a5f4f7335f7bdf98e54e2263949f /net | |
parent | cc63ec766b7821c8dc4dc1d1e980124aea96b553 (diff) | |
download | blackbird-op-linux-aa5f66d5a1df1c2b04bccdcb19711675c765d7c4.tar.gz blackbird-op-linux-aa5f66d5a1df1c2b04bccdcb19711675c765d7c4.zip |
cfg80211: fix sysfs registration race
My locking rework/race fixes caused a regression in the
registration, causing uevent notifications for wireless
devices before the device is really fully registered and
available in nl80211.
Fix this by moving the device_add() under rtnl and move
the rfkill to afterwards (it can't be under rtnl.)
Reported-and-tested-by: Maxime Bizon <mbizon@freebox.fr>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net')
-rw-r--r-- | net/wireless/core.c | 21 |
1 files changed, 13 insertions, 8 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index 67153964aad2..fe8d4f2be49b 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -566,18 +566,13 @@ int wiphy_register(struct wiphy *wiphy) /* check and set up bitrates */ ieee80211_set_bitrate_flags(wiphy); - + rtnl_lock(); res = device_add(&rdev->wiphy.dev); - if (res) - return res; - - res = rfkill_register(rdev->rfkill); if (res) { - device_del(&rdev->wiphy.dev); + rtnl_unlock(); return res; } - rtnl_lock(); /* set up regulatory info */ wiphy_regulatory_register(wiphy); @@ -606,6 +601,15 @@ int wiphy_register(struct wiphy *wiphy) rdev->wiphy.registered = true; rtnl_unlock(); + + res = rfkill_register(rdev->rfkill); + if (res) { + rfkill_destroy(rdev->rfkill); + rdev->rfkill = NULL; + wiphy_unregister(&rdev->wiphy); + return res; + } + return 0; } EXPORT_SYMBOL(wiphy_register); @@ -640,7 +644,8 @@ void wiphy_unregister(struct wiphy *wiphy) rtnl_unlock(); __count == 0; })); - rfkill_unregister(rdev->rfkill); + if (rdev->rfkill) + rfkill_unregister(rdev->rfkill); rtnl_lock(); rdev->wiphy.registered = false; |