aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/nl80211.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/nl80211.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/nl80211.c')
-rw-r--r--net/wireless/nl80211.c178
1 files changed, 36 insertions, 142 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 5bcf3a5b6465..74cdb1a0cf31 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)
59 int wiphy_idx = -1; 59 int wiphy_idx = -1;
60 int ifidx = -1; 60 int ifidx = -1;
61 61
62 assert_cfg80211_lock(); 62 ASSERT_RTNL();
63 63
64 if (!have_ifidx && !have_wdev_id) 64 if (!have_ifidx && !have_wdev_id)
65 return ERR_PTR(-EINVAL); 65 return ERR_PTR(-EINVAL);
@@ -80,7 +80,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
80 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx) 80 if (have_wdev_id && rdev->wiphy_idx != wiphy_idx)
81 continue; 81 continue;
82 82
83 mutex_lock(&rdev->devlist_mtx);
84 list_for_each_entry(wdev, &rdev->wdev_list, list) { 83 list_for_each_entry(wdev, &rdev->wdev_list, list) {
85 if (have_ifidx && wdev->netdev && 84 if (have_ifidx && wdev->netdev &&
86 wdev->netdev->ifindex == ifidx) { 85 wdev->netdev->ifindex == ifidx) {
@@ -92,7 +91,6 @@ __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
92 break; 91 break;
93 } 92 }
94 } 93 }
95 mutex_unlock(&rdev->devlist_mtx);
96 94
97 if (result) 95 if (result)
98 break; 96 break;
@@ -109,7 +107,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
109 struct cfg80211_registered_device *rdev = NULL, *tmp; 107 struct cfg80211_registered_device *rdev = NULL, *tmp;
110 struct net_device *netdev; 108 struct net_device *netdev;
111 109
112 assert_cfg80211_lock(); 110 ASSERT_RTNL();
113 111
114 if (!attrs[NL80211_ATTR_WIPHY] && 112 if (!attrs[NL80211_ATTR_WIPHY] &&
115 !attrs[NL80211_ATTR_IFINDEX] && 113 !attrs[NL80211_ATTR_IFINDEX] &&
@@ -128,14 +126,12 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
128 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32); 126 tmp = cfg80211_rdev_by_wiphy_idx(wdev_id >> 32);
129 if (tmp) { 127 if (tmp) {
130 /* make sure wdev exists */ 128 /* make sure wdev exists */
131 mutex_lock(&tmp->devlist_mtx);
132 list_for_each_entry(wdev, &tmp->wdev_list, list) { 129 list_for_each_entry(wdev, &tmp->wdev_list, list) {
133 if (wdev->identifier != (u32)wdev_id) 130 if (wdev->identifier != (u32)wdev_id)
134 continue; 131 continue;
135 found = true; 132 found = true;
136 break; 133 break;
137 } 134 }
138 mutex_unlock(&tmp->devlist_mtx);
139 135
140 if (!found) 136 if (!found)
141 tmp = NULL; 137 tmp = NULL;
@@ -182,19 +178,6 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
182/* 178/*
183 * This function returns a pointer to the driver 179 * This function returns a pointer to the driver
184 * that the genl_info item that is passed refers to. 180 * that the genl_info item that is passed refers to.
185 * If successful, it returns non-NULL and also locks
186 * the driver's mutex!
187 *
188 * This means that you need to call cfg80211_unlock_rdev()
189 * before being allowed to acquire &cfg80211_mutex!
190 *
191 * This is necessary because we need to lock the global
192 * mutex to get an item off the list safely, and then
193 * we lock the rdev mutex so it doesn't go away under us.
194 *
195 * We don't want to keep cfg80211_mutex locked
196 * for all the time in order to allow requests on
197 * other interfaces to go through at the same time.
198 * 181 *
199 * The result of this can be a PTR_ERR and hence must 182 * The result of this can be a PTR_ERR and hence must
200 * be checked with IS_ERR() for errors. 183 * be checked with IS_ERR() for errors.
@@ -202,20 +185,7 @@ __cfg80211_rdev_from_attrs(struct net *netns, struct nlattr **attrs)
202static struct cfg80211_registered_device * 185static struct cfg80211_registered_device *
203cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info) 186cfg80211_get_dev_from_info(struct net *netns, struct genl_info *info)
204{ 187{
205 struct cfg80211_registered_device *rdev; 188 return __cfg80211_rdev_from_attrs(netns, info->attrs);
206
207 mutex_lock(&cfg80211_mutex);
208 rdev = __cfg80211_rdev_from_attrs(netns, info->attrs);
209
210 /* if it is not an error we grab the lock on
211 * it to assure it won't be going away while
212 * we operate on it */
213 if (!IS_ERR(rdev))
214 mutex_lock(&rdev->mtx);
215
216 mutex_unlock(&cfg80211_mutex);
217
218 return rdev;
219} 189}
220 190
221/* policy for the attributes */ 191/* policy for the attributes */
@@ -456,7 +426,6 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
456 int err; 426 int err;
457 427
458 rtnl_lock(); 428 rtnl_lock();
459 mutex_lock(&cfg80211_mutex);
460 429
461 if (!cb->args[0]) { 430 if (!cb->args[0]) {
462 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 431 err = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
@@ -485,14 +454,12 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
485 *rdev = wiphy_to_dev(wiphy); 454 *rdev = wiphy_to_dev(wiphy);
486 *wdev = NULL; 455 *wdev = NULL;
487 456
488 mutex_lock(&(*rdev)->devlist_mtx);
489 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) { 457 list_for_each_entry(tmp, &(*rdev)->wdev_list, list) {
490 if (tmp->identifier == cb->args[1]) { 458 if (tmp->identifier == cb->args[1]) {
491 *wdev = tmp; 459 *wdev = tmp;
492 break; 460 break;
493 } 461 }
494 } 462 }
495 mutex_unlock(&(*rdev)->devlist_mtx);
496 463
497 if (!*wdev) { 464 if (!*wdev) {
498 err = -ENODEV; 465 err = -ENODEV;
@@ -500,19 +467,14 @@ static int nl80211_prepare_wdev_dump(struct sk_buff *skb,
500 } 467 }
501 } 468 }
502 469
503 cfg80211_lock_rdev(*rdev);
504
505 mutex_unlock(&cfg80211_mutex);
506 return 0; 470 return 0;
507 out_unlock: 471 out_unlock:
508 mutex_unlock(&cfg80211_mutex);
509 rtnl_unlock(); 472 rtnl_unlock();
510 return err; 473 return err;
511} 474}
512 475
513static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev) 476static void nl80211_finish_wdev_dump(struct cfg80211_registered_device *rdev)
514{ 477{
515 cfg80211_unlock_rdev(rdev);
516 rtnl_unlock(); 478 rtnl_unlock();
517} 479}
518 480
@@ -1568,7 +1530,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1568 struct nlattr **tb = nl80211_fam.attrbuf; 1530 struct nlattr **tb = nl80211_fam.attrbuf;
1569 int res; 1531 int res;
1570 1532
1571 mutex_lock(&cfg80211_mutex); 1533 rtnl_lock();
1572 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize, 1534 res = nlmsg_parse(cb->nlh, GENL_HDRLEN + nl80211_fam.hdrsize,
1573 tb, nl80211_fam.maxattr, nl80211_policy); 1535 tb, nl80211_fam.maxattr, nl80211_policy);
1574 if (res == 0) { 1536 if (res == 0) {
@@ -1582,10 +1544,8 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1582 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]); 1544 int ifidx = nla_get_u32(tb[NL80211_ATTR_IFINDEX]);
1583 1545
1584 netdev = dev_get_by_index(sock_net(skb->sk), ifidx); 1546 netdev = dev_get_by_index(sock_net(skb->sk), ifidx);
1585 if (!netdev) { 1547 if (!netdev)
1586 mutex_unlock(&cfg80211_mutex);
1587 return -ENODEV; 1548 return -ENODEV;
1588 }
1589 if (netdev->ieee80211_ptr) { 1549 if (netdev->ieee80211_ptr) {
1590 dev = wiphy_to_dev( 1550 dev = wiphy_to_dev(
1591 netdev->ieee80211_ptr->wiphy); 1551 netdev->ieee80211_ptr->wiphy);
@@ -1629,7 +1589,6 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1629 !skb->len && 1589 !skb->len &&
1630 cb->min_dump_alloc < 4096) { 1590 cb->min_dump_alloc < 4096) {
1631 cb->min_dump_alloc = 4096; 1591 cb->min_dump_alloc = 4096;
1632 mutex_unlock(&cfg80211_mutex);
1633 return 1; 1592 return 1;
1634 } 1593 }
1635 idx--; 1594 idx--;
@@ -1638,7 +1597,7 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb)
1638 } while (cb->args[1] > 0); 1597 } while (cb->args[1] > 0);
1639 break; 1598 break;
1640 } 1599 }
1641 mutex_unlock(&cfg80211_mutex); 1600 rtnl_unlock();
1642 1601
1643 cb->args[0] = idx; 1602 cb->args[0] = idx;
1644 1603
@@ -1793,7 +1752,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1793 if (result) 1752 if (result)
1794 return result; 1753 return result;
1795 1754
1796 mutex_lock(&rdev->devlist_mtx);
1797 switch (iftype) { 1755 switch (iftype) {
1798 case NL80211_IFTYPE_AP: 1756 case NL80211_IFTYPE_AP:
1799 case NL80211_IFTYPE_P2P_GO: 1757 case NL80211_IFTYPE_P2P_GO:
@@ -1817,7 +1775,6 @@ static int __nl80211_set_channel(struct cfg80211_registered_device *rdev,
1817 default: 1775 default:
1818 result = -EINVAL; 1776 result = -EINVAL;
1819 } 1777 }
1820 mutex_unlock(&rdev->devlist_mtx);
1821 1778
1822 return result; 1779 return result;
1823} 1780}
@@ -1866,6 +1823,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1866 u32 frag_threshold = 0, rts_threshold = 0; 1823 u32 frag_threshold = 0, rts_threshold = 0;
1867 u8 coverage_class = 0; 1824 u8 coverage_class = 0;
1868 1825
1826 ASSERT_RTNL();
1827
1869 /* 1828 /*
1870 * Try to find the wiphy and netdev. Normally this 1829 * Try to find the wiphy and netdev. Normally this
1871 * function shouldn't need the netdev, but this is 1830 * function shouldn't need the netdev, but this is
@@ -1875,31 +1834,25 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1875 * also passed a netdev to set_wiphy, so that it is 1834 * also passed a netdev to set_wiphy, so that it is
1876 * possible to let that go to the right netdev! 1835 * possible to let that go to the right netdev!
1877 */ 1836 */
1878 mutex_lock(&cfg80211_mutex);
1879 1837
1880 if (info->attrs[NL80211_ATTR_IFINDEX]) { 1838 if (info->attrs[NL80211_ATTR_IFINDEX]) {
1881 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]); 1839 int ifindex = nla_get_u32(info->attrs[NL80211_ATTR_IFINDEX]);
1882 1840
1883 netdev = dev_get_by_index(genl_info_net(info), ifindex); 1841 netdev = dev_get_by_index(genl_info_net(info), ifindex);
1884 if (netdev && netdev->ieee80211_ptr) { 1842 if (netdev && netdev->ieee80211_ptr)
1885 rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy); 1843 rdev = wiphy_to_dev(netdev->ieee80211_ptr->wiphy);
1886 mutex_lock(&rdev->mtx); 1844 else
1887 } else
1888 netdev = NULL; 1845 netdev = NULL;
1889 } 1846 }
1890 1847
1891 if (!netdev) { 1848 if (!netdev) {
1892 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info), 1849 rdev = __cfg80211_rdev_from_attrs(genl_info_net(info),
1893 info->attrs); 1850 info->attrs);
1894 if (IS_ERR(rdev)) { 1851 if (IS_ERR(rdev))
1895 mutex_unlock(&cfg80211_mutex);
1896 return PTR_ERR(rdev); 1852 return PTR_ERR(rdev);
1897 }
1898 wdev = NULL; 1853 wdev = NULL;
1899 netdev = NULL; 1854 netdev = NULL;
1900 result = 0; 1855 result = 0;
1901
1902 mutex_lock(&rdev->mtx);
1903 } else 1856 } else
1904 wdev = netdev->ieee80211_ptr; 1857 wdev = netdev->ieee80211_ptr;
1905 1858
@@ -1912,8 +1865,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
1912 result = cfg80211_dev_rename( 1865 result = cfg80211_dev_rename(
1913 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME])); 1866 rdev, nla_data(info->attrs[NL80211_ATTR_WIPHY_NAME]));
1914 1867
1915 mutex_unlock(&cfg80211_mutex);
1916
1917 if (result) 1868 if (result)
1918 goto bad_res; 1869 goto bad_res;
1919 1870
@@ -2120,7 +2071,6 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
2120 } 2071 }
2121 2072
2122 bad_res: 2073 bad_res:
2123 mutex_unlock(&rdev->mtx);
2124 if (netdev) 2074 if (netdev)
2125 dev_put(netdev); 2075 dev_put(netdev);
2126 return result; 2076 return result;
@@ -2218,7 +2168,7 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
2218 struct cfg80211_registered_device *rdev; 2168 struct cfg80211_registered_device *rdev;
2219 struct wireless_dev *wdev; 2169 struct wireless_dev *wdev;
2220 2170
2221 mutex_lock(&cfg80211_mutex); 2171 rtnl_lock();
2222 list_for_each_entry(rdev, &cfg80211_rdev_list, list) { 2172 list_for_each_entry(rdev, &cfg80211_rdev_list, list) {
2223 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk))) 2173 if (!net_eq(wiphy_net(&rdev->wiphy), sock_net(skb->sk)))
2224 continue; 2174 continue;
@@ -2228,7 +2178,6 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
2228 } 2178 }
2229 if_idx = 0; 2179 if_idx = 0;
2230 2180
2231 mutex_lock(&rdev->devlist_mtx);
2232 list_for_each_entry(wdev, &rdev->wdev_list, list) { 2181 list_for_each_entry(wdev, &rdev->wdev_list, list) {
2233 if (if_idx < if_start) { 2182 if (if_idx < if_start) {
2234 if_idx++; 2183 if_idx++;
@@ -2237,17 +2186,15 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
2237 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid, 2186 if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
2238 cb->nlh->nlmsg_seq, NLM_F_MULTI, 2187 cb->nlh->nlmsg_seq, NLM_F_MULTI,
2239 rdev, wdev) < 0) { 2188 rdev, wdev) < 0) {
2240 mutex_unlock(&rdev->devlist_mtx);
2241 goto out; 2189 goto out;
2242 } 2190 }
2243 if_idx++; 2191 if_idx++;
2244 } 2192 }
2245 mutex_unlock(&rdev->devlist_mtx);
2246 2193
2247 wp_idx++; 2194 wp_idx++;
2248 } 2195 }
2249 out: 2196 out:
2250 mutex_unlock(&cfg80211_mutex); 2197 rtnl_unlock();
2251 2198
2252 cb->args[0] = wp_idx; 2199 cb->args[0] = wp_idx;
2253 cb->args[1] = if_idx; 2200 cb->args[1] = if_idx;
@@ -2480,11 +2427,9 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
2480 INIT_LIST_HEAD(&wdev->mgmt_registrations); 2427 INIT_LIST_HEAD(&wdev->mgmt_registrations);
2481 spin_lock_init(&wdev->mgmt_registrations_lock); 2428 spin_lock_init(&wdev->mgmt_registrations_lock);
2482 2429
2483 mutex_lock(&rdev->devlist_mtx);
2484 wdev->identifier = ++rdev->wdev_id; 2430 wdev->identifier = ++rdev->wdev_id;
2485 list_add_rcu(&wdev->list, &rdev->wdev_list); 2431 list_add_rcu(&wdev->list, &rdev->wdev_list);
2486 rdev->devlist_generation++; 2432 rdev->devlist_generation++;
2487 mutex_unlock(&rdev->devlist_mtx);
2488 break; 2433 break;
2489 default: 2434 default:
2490 break; 2435 break;
@@ -2993,8 +2938,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
2993 struct wireless_dev *wdev; 2938 struct wireless_dev *wdev;
2994 bool ret = false; 2939 bool ret = false;
2995 2940
2996 mutex_lock(&rdev->devlist_mtx);
2997
2998 list_for_each_entry(wdev, &rdev->wdev_list, list) { 2941 list_for_each_entry(wdev, &rdev->wdev_list, list) {
2999 if (wdev->iftype != NL80211_IFTYPE_AP && 2942 if (wdev->iftype != NL80211_IFTYPE_AP &&
3000 wdev->iftype != NL80211_IFTYPE_P2P_GO) 2943 wdev->iftype != NL80211_IFTYPE_P2P_GO)
@@ -3008,8 +2951,6 @@ static bool nl80211_get_ap_channel(struct cfg80211_registered_device *rdev,
3008 break; 2951 break;
3009 } 2952 }
3010 2953
3011 mutex_unlock(&rdev->devlist_mtx);
3012
3013 return ret; 2954 return ret;
3014} 2955}
3015 2956
@@ -3171,13 +3112,10 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
3171 params.radar_required = true; 3112 params.radar_required = true;
3172 } 3113 }
3173 3114
3174 mutex_lock(&rdev->devlist_mtx);
3175 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, 3115 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
3176 params.chandef.chan, 3116 params.chandef.chan,
3177 CHAN_MODE_SHARED, 3117 CHAN_MODE_SHARED,
3178 radar_detect_width); 3118 radar_detect_width);
3179 mutex_unlock(&rdev->devlist_mtx);
3180
3181 if (err) 3119 if (err)
3182 return err; 3120 return err;
3183 3121
@@ -4914,18 +4852,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
4914 void *hdr = NULL; 4852 void *hdr = NULL;
4915 struct nlattr *nl_reg_rules; 4853 struct nlattr *nl_reg_rules;
4916 unsigned int i; 4854 unsigned int i;
4917 int err = -EINVAL;
4918
4919 mutex_lock(&cfg80211_mutex);
4920 4855
4921 if (!cfg80211_regdomain) 4856 if (!cfg80211_regdomain)
4922 goto out; 4857 return -EINVAL;
4923 4858
4924 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 4859 msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
4925 if (!msg) { 4860 if (!msg)
4926 err = -ENOBUFS; 4861 return -ENOBUFS;
4927 goto out;
4928 }
4929 4862
4930 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0, 4863 hdr = nl80211hdr_put(msg, info->snd_portid, info->snd_seq, 0,
4931 NL80211_CMD_GET_REG); 4864 NL80211_CMD_GET_REG);
@@ -4984,8 +4917,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info)
4984 nla_nest_end(msg, nl_reg_rules); 4917 nla_nest_end(msg, nl_reg_rules);
4985 4918
4986 genlmsg_end(msg, hdr); 4919 genlmsg_end(msg, hdr);
4987 err = genlmsg_reply(msg, info); 4920 return genlmsg_reply(msg, info);
4988 goto out;
4989 4921
4990nla_put_failure_rcu: 4922nla_put_failure_rcu:
4991 rcu_read_unlock(); 4923 rcu_read_unlock();
@@ -4993,10 +4925,7 @@ nla_put_failure:
4993 genlmsg_cancel(msg, hdr); 4925 genlmsg_cancel(msg, hdr);
4994put_failure: 4926put_failure:
4995 nlmsg_free(msg); 4927 nlmsg_free(msg);
4996 err = -EMSGSIZE; 4928 return -EMSGSIZE;
4997out:
4998 mutex_unlock(&cfg80211_mutex);
4999 return err;
5000} 4929}
5001 4930
5002static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) 4931static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
@@ -5062,12 +4991,9 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info)
5062 } 4991 }
5063 } 4992 }
5064 4993
5065 mutex_lock(&cfg80211_mutex);
5066
5067 r = set_regdom(rd); 4994 r = set_regdom(rd);
5068 /* set_regdom took ownership */ 4995 /* set_regdom took ownership */
5069 rd = NULL; 4996 rd = NULL;
5070 mutex_unlock(&cfg80211_mutex);
5071 4997
5072 bad_reg: 4998 bad_reg:
5073 kfree(rd); 4999 kfree(rd);
@@ -5117,7 +5043,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5117 if (!rdev->ops->scan) 5043 if (!rdev->ops->scan)
5118 return -EOPNOTSUPP; 5044 return -EOPNOTSUPP;
5119 5045
5120 mutex_lock(&rdev->sched_scan_mtx);
5121 if (rdev->scan_req) { 5046 if (rdev->scan_req) {
5122 err = -EBUSY; 5047 err = -EBUSY;
5123 goto unlock; 5048 goto unlock;
@@ -5303,7 +5228,6 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info)
5303 } 5228 }
5304 5229
5305 unlock: 5230 unlock:
5306 mutex_unlock(&rdev->sched_scan_mtx);
5307 return err; 5231 return err;
5308} 5232}
5309 5233
@@ -5375,8 +5299,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5375 if (ie_len > wiphy->max_sched_scan_ie_len) 5299 if (ie_len > wiphy->max_sched_scan_ie_len)
5376 return -EINVAL; 5300 return -EINVAL;
5377 5301
5378 mutex_lock(&rdev->sched_scan_mtx);
5379
5380 if (rdev->sched_scan_req) { 5302 if (rdev->sched_scan_req) {
5381 err = -EINPROGRESS; 5303 err = -EINPROGRESS;
5382 goto out; 5304 goto out;
@@ -5544,7 +5466,6 @@ static int nl80211_start_sched_scan(struct sk_buff *skb,
5544out_free: 5466out_free:
5545 kfree(request); 5467 kfree(request);
5546out: 5468out:
5547 mutex_unlock(&rdev->sched_scan_mtx);
5548 return err; 5469 return err;
5549} 5470}
5550 5471
@@ -5552,17 +5473,12 @@ static int nl80211_stop_sched_scan(struct sk_buff *skb,
5552 struct genl_info *info) 5473 struct genl_info *info)
5553{ 5474{
5554 struct cfg80211_registered_device *rdev = info->user_ptr[0]; 5475 struct cfg80211_registered_device *rdev = info->user_ptr[0];
5555 int err;
5556 5476
5557 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || 5477 if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) ||
5558 !rdev->ops->sched_scan_stop) 5478 !rdev->ops->sched_scan_stop)
5559 return -EOPNOTSUPP; 5479 return -EOPNOTSUPP;
5560 5480
5561 mutex_lock(&rdev->sched_scan_mtx); 5481 return __cfg80211_stop_sched_scan(rdev, false);
5562 err = __cfg80211_stop_sched_scan(rdev, false);
5563 mutex_unlock(&rdev->sched_scan_mtx);
5564
5565 return err;
5566} 5482}
5567 5483
5568static int nl80211_start_radar_detection(struct sk_buff *skb, 5484static int nl80211_start_radar_detection(struct sk_buff *skb,
@@ -5594,12 +5510,11 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5594 if (!rdev->ops->start_radar_detection) 5510 if (!rdev->ops->start_radar_detection)
5595 return -EOPNOTSUPP; 5511 return -EOPNOTSUPP;
5596 5512
5597 mutex_lock(&rdev->devlist_mtx);
5598 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, 5513 err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype,
5599 chandef.chan, CHAN_MODE_SHARED, 5514 chandef.chan, CHAN_MODE_SHARED,
5600 BIT(chandef.width)); 5515 BIT(chandef.width));
5601 if (err) 5516 if (err)
5602 goto err_locked; 5517 return err;
5603 5518
5604 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); 5519 err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef);
5605 if (!err) { 5520 if (!err) {
@@ -5607,9 +5522,6 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
5607 wdev->cac_started = true; 5522 wdev->cac_started = true;
5608 wdev->cac_start_time = jiffies; 5523 wdev->cac_start_time = jiffies;
5609 } 5524 }
5610err_locked:
5611 mutex_unlock(&rdev->devlist_mtx);
5612
5613 return err; 5525 return err;
5614} 5526}
5615 5527
@@ -6472,6 +6384,8 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6472 void *data = NULL; 6384 void *data = NULL;
6473 int data_len = 0; 6385 int data_len = 0;
6474 6386
6387 rtnl_lock();
6388
6475 if (cb->args[0]) { 6389 if (cb->args[0]) {
6476 /* 6390 /*
6477 * 0 is a valid index, but not valid for args[0], 6391 * 0 is a valid index, but not valid for args[0],
@@ -6483,18 +6397,16 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6483 nl80211_fam.attrbuf, nl80211_fam.maxattr, 6397 nl80211_fam.attrbuf, nl80211_fam.maxattr,
6484 nl80211_policy); 6398 nl80211_policy);
6485 if (err) 6399 if (err)
6486 return err; 6400 goto out_err;
6487 6401
6488 mutex_lock(&cfg80211_mutex);
6489 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk), 6402 rdev = __cfg80211_rdev_from_attrs(sock_net(skb->sk),
6490 nl80211_fam.attrbuf); 6403 nl80211_fam.attrbuf);
6491 if (IS_ERR(rdev)) { 6404 if (IS_ERR(rdev)) {
6492 mutex_unlock(&cfg80211_mutex); 6405 err = PTR_ERR(rdev);
6493 return PTR_ERR(rdev); 6406 goto out_err;
6494 } 6407 }
6495 phy_idx = rdev->wiphy_idx; 6408 phy_idx = rdev->wiphy_idx;
6496 rdev = NULL; 6409 rdev = NULL;
6497 mutex_unlock(&cfg80211_mutex);
6498 6410
6499 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA]) 6411 if (nl80211_fam.attrbuf[NL80211_ATTR_TESTDATA])
6500 cb->args[1] = 6412 cb->args[1] =
@@ -6506,14 +6418,11 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6506 data_len = nla_len((void *)cb->args[1]); 6418 data_len = nla_len((void *)cb->args[1]);
6507 } 6419 }
6508 6420
6509 mutex_lock(&cfg80211_mutex);
6510 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx); 6421 rdev = cfg80211_rdev_by_wiphy_idx(phy_idx);
6511 if (!rdev) { 6422 if (!rdev) {
6512 mutex_unlock(&cfg80211_mutex); 6423 err = -ENOENT;
6513 return -ENOENT; 6424 goto out_err;
6514 } 6425 }
6515 cfg80211_lock_rdev(rdev);
6516 mutex_unlock(&cfg80211_mutex);
6517 6426
6518 if (!rdev->ops->testmode_dump) { 6427 if (!rdev->ops->testmode_dump) {
6519 err = -EOPNOTSUPP; 6428 err = -EOPNOTSUPP;
@@ -6554,7 +6463,7 @@ static int nl80211_testmode_dump(struct sk_buff *skb,
6554 /* see above */ 6463 /* see above */
6555 cb->args[0] = phy_idx + 1; 6464 cb->args[0] = phy_idx + 1;
6556 out_err: 6465 out_err:
6557 cfg80211_unlock_rdev(rdev); 6466 rtnl_unlock();
6558 return err; 6467 return err;
6559} 6468}
6560 6469
@@ -8189,9 +8098,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
8189 if (wdev->p2p_started) 8098 if (wdev->p2p_started)
8190 return 0; 8099 return 0;
8191 8100
8192 mutex_lock(&rdev->devlist_mtx);
8193 err = cfg80211_can_add_interface(rdev, wdev->iftype); 8101 err = cfg80211_can_add_interface(rdev, wdev->iftype);
8194 mutex_unlock(&rdev->devlist_mtx);
8195 if (err) 8102 if (err)
8196 return err; 8103 return err;
8197 8104
@@ -8200,9 +8107,7 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
8200 return err; 8107 return err;
8201 8108
8202 wdev->p2p_started = true; 8109 wdev->p2p_started = true;
8203 mutex_lock(&rdev->devlist_mtx);
8204 rdev->opencount++; 8110 rdev->opencount++;
8205 mutex_unlock(&rdev->devlist_mtx);
8206 8111
8207 return 0; 8112 return 0;
8208} 8113}
@@ -8218,11 +8123,7 @@ static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info)
8218 if (!rdev->ops->stop_p2p_device) 8123 if (!rdev->ops->stop_p2p_device)
8219 return -EOPNOTSUPP; 8124 return -EOPNOTSUPP;
8220 8125
8221 mutex_lock(&rdev->devlist_mtx);
8222 mutex_lock(&rdev->sched_scan_mtx);
8223 cfg80211_stop_p2p_device(rdev, wdev); 8126 cfg80211_stop_p2p_device(rdev, wdev);
8224 mutex_unlock(&rdev->sched_scan_mtx);
8225 mutex_unlock(&rdev->devlist_mtx);
8226 8127
8227 return 0; 8128 return 0;
8228} 8129}
@@ -8365,11 +8266,11 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8365 info->user_ptr[0] = rdev; 8266 info->user_ptr[0] = rdev;
8366 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV || 8267 } else if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV ||
8367 ops->internal_flags & NL80211_FLAG_NEED_WDEV) { 8268 ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
8368 mutex_lock(&cfg80211_mutex); 8269 ASSERT_RTNL();
8270
8369 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info), 8271 wdev = __cfg80211_wdev_from_attrs(genl_info_net(info),
8370 info->attrs); 8272 info->attrs);
8371 if (IS_ERR(wdev)) { 8273 if (IS_ERR(wdev)) {
8372 mutex_unlock(&cfg80211_mutex);
8373 if (rtnl) 8274 if (rtnl)
8374 rtnl_unlock(); 8275 rtnl_unlock();
8375 return PTR_ERR(wdev); 8276 return PTR_ERR(wdev);
@@ -8380,7 +8281,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8380 8281
8381 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) { 8282 if (ops->internal_flags & NL80211_FLAG_NEED_NETDEV) {
8382 if (!dev) { 8283 if (!dev) {
8383 mutex_unlock(&cfg80211_mutex);
8384 if (rtnl) 8284 if (rtnl)
8385 rtnl_unlock(); 8285 rtnl_unlock();
8386 return -EINVAL; 8286 return -EINVAL;
@@ -8394,7 +8294,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8394 if (dev) { 8294 if (dev) {
8395 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP && 8295 if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP &&
8396 !netif_running(dev)) { 8296 !netif_running(dev)) {
8397 mutex_unlock(&cfg80211_mutex);
8398 if (rtnl) 8297 if (rtnl)
8399 rtnl_unlock(); 8298 rtnl_unlock();
8400 return -ENETDOWN; 8299 return -ENETDOWN;
@@ -8403,17 +8302,12 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8403 dev_hold(dev); 8302 dev_hold(dev);
8404 } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { 8303 } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) {
8405 if (!wdev->p2p_started) { 8304 if (!wdev->p2p_started) {
8406 mutex_unlock(&cfg80211_mutex);
8407 if (rtnl) 8305 if (rtnl)
8408 rtnl_unlock(); 8306 rtnl_unlock();
8409 return -ENETDOWN; 8307 return -ENETDOWN;
8410 } 8308 }
8411 } 8309 }
8412 8310
8413 cfg80211_lock_rdev(rdev);
8414
8415 mutex_unlock(&cfg80211_mutex);
8416
8417 info->user_ptr[0] = rdev; 8311 info->user_ptr[0] = rdev;
8418 } 8312 }
8419 8313
@@ -8423,8 +8317,6 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
8423static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb, 8317static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
8424 struct genl_info *info) 8318 struct genl_info *info)
8425{ 8319{
8426 if (info->user_ptr[0])
8427 cfg80211_unlock_rdev(info->user_ptr[0]);
8428 if (info->user_ptr[1]) { 8320 if (info->user_ptr[1]) {
8429 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) { 8321 if (ops->internal_flags & NL80211_FLAG_NEED_WDEV) {
8430 struct wireless_dev *wdev = info->user_ptr[1]; 8322 struct wireless_dev *wdev = info->user_ptr[1];
@@ -8446,7 +8338,8 @@ static struct genl_ops nl80211_ops[] = {
8446 .dumpit = nl80211_dump_wiphy, 8338 .dumpit = nl80211_dump_wiphy,
8447 .policy = nl80211_policy, 8339 .policy = nl80211_policy,
8448 /* can be retrieved by unprivileged users */ 8340 /* can be retrieved by unprivileged users */
8449 .internal_flags = NL80211_FLAG_NEED_WIPHY, 8341 .internal_flags = NL80211_FLAG_NEED_WIPHY |
8342 NL80211_FLAG_NEED_RTNL,
8450 }, 8343 },
8451 { 8344 {
8452 .cmd = NL80211_CMD_SET_WIPHY, 8345 .cmd = NL80211_CMD_SET_WIPHY,
@@ -8461,7 +8354,8 @@ static struct genl_ops nl80211_ops[] = {
8461 .dumpit = nl80211_dump_interface, 8354 .dumpit = nl80211_dump_interface,
8462 .policy = nl80211_policy, 8355 .policy = nl80211_policy,
8463 /* can be retrieved by unprivileged users */ 8356 /* can be retrieved by unprivileged users */
8464 .internal_flags = NL80211_FLAG_NEED_WDEV, 8357 .internal_flags = NL80211_FLAG_NEED_WDEV |
8358 NL80211_FLAG_NEED_RTNL,
8465 }, 8359 },
8466 { 8360 {
8467 .cmd = NL80211_CMD_SET_INTERFACE, 8361 .cmd = NL80211_CMD_SET_INTERFACE,
@@ -8620,6 +8514,7 @@ static struct genl_ops nl80211_ops[] = {
8620 .cmd = NL80211_CMD_GET_REG, 8514 .cmd = NL80211_CMD_GET_REG,
8621 .doit = nl80211_get_reg, 8515 .doit = nl80211_get_reg,
8622 .policy = nl80211_policy, 8516 .policy = nl80211_policy,
8517 .internal_flags = NL80211_FLAG_NEED_RTNL,
8623 /* can be retrieved by unprivileged users */ 8518 /* can be retrieved by unprivileged users */
8624 }, 8519 },
8625 { 8520 {
@@ -8627,6 +8522,7 @@ static struct genl_ops nl80211_ops[] = {
8627 .doit = nl80211_set_reg, 8522 .doit = nl80211_set_reg,
8628 .policy = nl80211_policy, 8523 .policy = nl80211_policy,
8629 .flags = GENL_ADMIN_PERM, 8524 .flags = GENL_ADMIN_PERM,
8525 .internal_flags = NL80211_FLAG_NEED_RTNL,
8630 }, 8526 },
8631 { 8527 {
8632 .cmd = NL80211_CMD_REQ_SET_REG, 8528 .cmd = NL80211_CMD_REQ_SET_REG,
@@ -9082,8 +8978,6 @@ static int nl80211_add_scan_req(struct sk_buff *msg,
9082 struct nlattr *nest; 8978 struct nlattr *nest;
9083 int i; 8979 int i;
9084 8980
9085 lockdep_assert_held(&rdev->sched_scan_mtx);
9086
9087 if (WARN_ON(!req)) 8981 if (WARN_ON(!req))
9088 return 0; 8982 return 0;
9089 8983