aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/core.c
diff options
context:
space:
mode:
authorMaxime Bizon <mbizon@freebox.fr>2010-07-21 11:21:38 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-21 15:13:42 -0400
commit5a652052fedbd7869572c757dd2ffc2ed420c69d (patch)
treec147fefc826f74e84a887a069235c22eadc0f561 /net/wireless/core.c
parentacd82aa868c2133149370c18d85f8005fbf5611e (diff)
cfg80211: fix race between sysfs and cfg80211
device_add() is called before adding the phy to the cfg80211 device list. So if a userspace program uses sysfs uevents to detect new phy devices, and queries nl80211 to get phy info, it can get ENODEV even though the phy exists in sysfs. An easy workaround is to hold the cfg80211 mutex until the phy is present in sysfs/cfg80211/debugfs. Signed-off-by: Maxime Bizon <mbizon@freebox.fr> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless/core.c')
-rw-r--r--net/wireless/core.c14
1 files changed, 8 insertions, 6 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 47fcfd0eebc..f65c6494ede 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -472,24 +472,22 @@ int wiphy_register(struct wiphy *wiphy)
472 /* check and set up bitrates */ 472 /* check and set up bitrates */
473 ieee80211_set_bitrate_flags(wiphy); 473 ieee80211_set_bitrate_flags(wiphy);
474 474
475 mutex_lock(&cfg80211_mutex);
476
475 res = device_add(&rdev->wiphy.dev); 477 res = device_add(&rdev->wiphy.dev);
476 if (res) 478 if (res)
477 return res; 479 goto out_unlock;
478 480
479 res = rfkill_register(rdev->rfkill); 481 res = rfkill_register(rdev->rfkill);
480 if (res) 482 if (res)
481 goto out_rm_dev; 483 goto out_rm_dev;
482 484
483 mutex_lock(&cfg80211_mutex);
484
485 /* set up regulatory info */ 485 /* set up regulatory info */
486 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE); 486 wiphy_update_regulatory(wiphy, NL80211_REGDOM_SET_BY_CORE);
487 487
488 list_add_rcu(&rdev->list, &cfg80211_rdev_list); 488 list_add_rcu(&rdev->list, &cfg80211_rdev_list);
489 cfg80211_rdev_list_generation++; 489 cfg80211_rdev_list_generation++;
490 490
491 mutex_unlock(&cfg80211_mutex);
492
493 /* add to debugfs */ 491 /* add to debugfs */
494 rdev->wiphy.debugfsdir = 492 rdev->wiphy.debugfsdir =
495 debugfs_create_dir(wiphy_name(&rdev->wiphy), 493 debugfs_create_dir(wiphy_name(&rdev->wiphy),
@@ -509,11 +507,15 @@ int wiphy_register(struct wiphy *wiphy)
509 } 507 }
510 508
511 cfg80211_debugfs_rdev_add(rdev); 509 cfg80211_debugfs_rdev_add(rdev);
510 mutex_unlock(&cfg80211_mutex);
512 511
513 return 0; 512 return 0;
514 513
515 out_rm_dev: 514out_rm_dev:
516 device_del(&rdev->wiphy.dev); 515 device_del(&rdev->wiphy.dev);
516
517out_unlock:
518 mutex_unlock(&cfg80211_mutex);
517 return res; 519 return res;
518} 520}
519EXPORT_SYMBOL(wiphy_register); 521EXPORT_SYMBOL(wiphy_register);