aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/reg.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2013-05-08 15:45:15 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-05-24 18:02:15 -0400
commit5fe231e873729fa2f57cdc417d5c1f80871e2d7d (patch)
tree48810991fa4cf4faa69c0a992fdaf962feb6edda /net/wireless/reg.c
parent73810b77def898b43a97638478692922b7f820eb (diff)
cfg80211: vastly simplify locking
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>
Diffstat (limited to 'net/wireless/reg.c')
-rw-r--r--net/wireless/reg.c36
1 files changed, 12 insertions, 24 deletions
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index cc35fbaa4578..e76559618588 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -377,7 +377,7 @@ static void reg_regdb_search(struct work_struct *work)
377 const struct ieee80211_regdomain *curdom, *regdom = NULL; 377 const struct ieee80211_regdomain *curdom, *regdom = NULL;
378 int i; 378 int i;
379 379
380 mutex_lock(&cfg80211_mutex); 380 rtnl_lock();
381 381
382 mutex_lock(&reg_regdb_search_mutex); 382 mutex_lock(&reg_regdb_search_mutex);
383 while (!list_empty(&reg_regdb_search_list)) { 383 while (!list_empty(&reg_regdb_search_list)) {
@@ -402,7 +402,7 @@ static void reg_regdb_search(struct work_struct *work)
402 if (!IS_ERR_OR_NULL(regdom)) 402 if (!IS_ERR_OR_NULL(regdom))
403 set_regdom(regdom); 403 set_regdom(regdom);
404 404
405 mutex_unlock(&cfg80211_mutex); 405 rtnl_unlock();
406} 406}
407 407
408static DECLARE_WORK(reg_regdb_work, reg_regdb_search); 408static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
@@ -1225,7 +1225,7 @@ static void update_all_wiphy_regulatory(enum nl80211_reg_initiator initiator)
1225 struct cfg80211_registered_device *rdev; 1225 struct cfg80211_registered_device *rdev;
1226 struct wiphy *wiphy; 1226 struct wiphy *wiphy;
1227 1227
1228 assert_cfg80211_lock(); 1228 ASSERT_RTNL();
1229 1229
1230 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 1230 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
1231 wiphy = &rdev->wiphy; 1231 wiphy = &rdev->wiphy;
@@ -1570,21 +1570,19 @@ static void reg_process_pending_hints(void)
1570{ 1570{
1571 struct regulatory_request *reg_request, *lr; 1571 struct regulatory_request *reg_request, *lr;
1572 1572
1573 mutex_lock(&cfg80211_mutex);
1574 mutex_lock(&reg_mutex);
1575 lr = get_last_request(); 1573 lr = get_last_request();
1576 1574
1577 /* When last_request->processed becomes true this will be rescheduled */ 1575 /* When last_request->processed becomes true this will be rescheduled */
1578 if (lr && !lr->processed) { 1576 if (lr && !lr->processed) {
1579 REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n"); 1577 REG_DBG_PRINT("Pending regulatory request, waiting for it to be processed...\n");
1580 goto out; 1578 return;
1581 } 1579 }
1582 1580
1583 spin_lock(&reg_requests_lock); 1581 spin_lock(&reg_requests_lock);
1584 1582
1585 if (list_empty(&reg_requests_list)) { 1583 if (list_empty(&reg_requests_list)) {
1586 spin_unlock(&reg_requests_lock); 1584 spin_unlock(&reg_requests_lock);
1587 goto out; 1585 return;
1588 } 1586 }
1589 1587
1590 reg_request = list_first_entry(&reg_requests_list, 1588 reg_request = list_first_entry(&reg_requests_list,
@@ -1595,10 +1593,6 @@ static void reg_process_pending_hints(void)
1595 spin_unlock(&reg_requests_lock); 1593 spin_unlock(&reg_requests_lock);
1596 1594
1597 reg_process_hint(reg_request, reg_request->initiator); 1595 reg_process_hint(reg_request, reg_request->initiator);
1598
1599out:
1600 mutex_unlock(&reg_mutex);
1601 mutex_unlock(&cfg80211_mutex);
1602} 1596}
1603 1597
1604/* Processes beacon hints -- this has nothing to do with country IEs */ 1598/* Processes beacon hints -- this has nothing to do with country IEs */
@@ -1607,9 +1601,6 @@ static void reg_process_pending_beacon_hints(void)
1607 struct cfg80211_registered_device *rdev; 1601 struct cfg80211_registered_device *rdev;
1608 struct reg_beacon *pending_beacon, *tmp; 1602 struct reg_beacon *pending_beacon, *tmp;
1609 1603
1610 mutex_lock(&cfg80211_mutex);
1611 mutex_lock(&reg_mutex);
1612
1613 /* This goes through the _pending_ beacon list */ 1604 /* This goes through the _pending_ beacon list */
1614 spin_lock_bh(&reg_pending_beacons_lock); 1605 spin_lock_bh(&reg_pending_beacons_lock);
1615 1606
@@ -1626,14 +1617,16 @@ static void reg_process_pending_beacon_hints(void)
1626 } 1617 }
1627 1618
1628 spin_unlock_bh(&reg_pending_beacons_lock); 1619 spin_unlock_bh(&reg_pending_beacons_lock);
1629 mutex_unlock(&reg_mutex);
1630 mutex_unlock(&cfg80211_mutex);
1631} 1620}
1632 1621
1633static void reg_todo(struct work_struct *work) 1622static void reg_todo(struct work_struct *work)
1634{ 1623{
1624 rtnl_lock();
1625 mutex_lock(&reg_mutex);
1635 reg_process_pending_hints(); 1626 reg_process_pending_hints();
1636 reg_process_pending_beacon_hints(); 1627 reg_process_pending_beacon_hints();
1628 mutex_unlock(&reg_mutex);
1629 rtnl_unlock();
1637} 1630}
1638 1631
1639static void queue_regulatory_request(struct regulatory_request *request) 1632static void queue_regulatory_request(struct regulatory_request *request)
@@ -1717,10 +1710,6 @@ int regulatory_hint(struct wiphy *wiphy, const char *alpha2)
1717} 1710}
1718EXPORT_SYMBOL(regulatory_hint); 1711EXPORT_SYMBOL(regulatory_hint);
1719 1712
1720/*
1721 * We hold wdev_lock() here so we cannot hold cfg80211_mutex() and
1722 * therefore cannot iterate over the rdev list here.
1723 */
1724void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band, 1713void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
1725 const u8 *country_ie, u8 country_ie_len) 1714 const u8 *country_ie, u8 country_ie_len)
1726{ 1715{
@@ -1752,7 +1741,7 @@ void regulatory_hint_11d(struct wiphy *wiphy, enum ieee80211_band band,
1752 /* 1741 /*
1753 * We will run this only upon a successful connection on cfg80211. 1742 * We will run this only upon a successful connection on cfg80211.
1754 * We leave conflict resolution to the workqueue, where can hold 1743 * We leave conflict resolution to the workqueue, where can hold
1755 * cfg80211_mutex. 1744 * the RTNL.
1756 */ 1745 */
1757 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && 1746 if (lr->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1758 lr->wiphy_idx != WIPHY_IDX_INVALID) 1747 lr->wiphy_idx != WIPHY_IDX_INVALID)
@@ -1858,7 +1847,8 @@ static void restore_regulatory_settings(bool reset_user)
1858 LIST_HEAD(tmp_reg_req_list); 1847 LIST_HEAD(tmp_reg_req_list);
1859 struct cfg80211_registered_device *rdev; 1848 struct cfg80211_registered_device *rdev;
1860 1849
1861 mutex_lock(&cfg80211_mutex); 1850 ASSERT_RTNL();
1851
1862 mutex_lock(&reg_mutex); 1852 mutex_lock(&reg_mutex);
1863 1853
1864 reset_regdomains(true, &world_regdom); 1854 reset_regdomains(true, &world_regdom);
@@ -1915,7 +1905,6 @@ static void restore_regulatory_settings(bool reset_user)
1915 spin_unlock(&reg_requests_lock); 1905 spin_unlock(&reg_requests_lock);
1916 1906
1917 mutex_unlock(&reg_mutex); 1907 mutex_unlock(&reg_mutex);
1918 mutex_unlock(&cfg80211_mutex);
1919 1908
1920 REG_DBG_PRINT("Kicking the queue\n"); 1909 REG_DBG_PRINT("Kicking the queue\n");
1921 1910
@@ -2297,7 +2286,6 @@ void wiphy_regulatory_register(struct wiphy *wiphy)
2297 mutex_unlock(&reg_mutex); 2286 mutex_unlock(&reg_mutex);
2298} 2287}
2299 2288
2300/* Caller must hold cfg80211_mutex */
2301void wiphy_regulatory_deregister(struct wiphy *wiphy) 2289void wiphy_regulatory_deregister(struct wiphy *wiphy)
2302{ 2290{
2303 struct wiphy *request_wiphy = NULL; 2291 struct wiphy *request_wiphy = NULL;