diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-03-12 04:55:09 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-03-27 20:12:56 -0400 |
commit | 3b85875a252dbbd95c2e04d73639719a0a79634e (patch) | |
tree | 573142df787d9ccd52944695478546f543489504 /net/wireless | |
parent | 8f655dde240293f3b82313cae91c64ffd7b64c50 (diff) |
nl80211: rework locking
When I added scanning to cfg80211, we got a lock dependency like this:
rtnl --> cfg80211_mtx
nl80211, on the other hand, has the reverse lock dependency:
cfg80211_mtx --> rtnl
which clearly is a bad idea. This patch reworks nl80211 to take these
two locks in the other order to fix the possible, and easily
triggerable, deadlock.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/wireless')
-rw-r--r-- | net/wireless/nl80211.c | 271 |
1 files changed, 166 insertions, 105 deletions
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 58ee1b1aff89..a3ecf8d73898 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -602,9 +602,12 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
602 | 602 | ||
603 | memset(¶ms, 0, sizeof(params)); | 603 | memset(¶ms, 0, sizeof(params)); |
604 | 604 | ||
605 | rtnl_lock(); | ||
606 | |||
605 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 607 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
606 | if (err) | 608 | if (err) |
607 | return err; | 609 | goto unlock_rtnl; |
610 | |||
608 | ifindex = dev->ifindex; | 611 | ifindex = dev->ifindex; |
609 | type = dev->ieee80211_ptr->iftype; | 612 | type = dev->ieee80211_ptr->iftype; |
610 | dev_put(dev); | 613 | dev_put(dev); |
@@ -641,17 +644,17 @@ static int nl80211_set_interface(struct sk_buff *skb, struct genl_info *info) | |||
641 | if (!err) | 644 | if (!err) |
642 | flags = &_flags; | 645 | flags = &_flags; |
643 | } | 646 | } |
644 | rtnl_lock(); | 647 | |
645 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, | 648 | err = drv->ops->change_virtual_intf(&drv->wiphy, ifindex, |
646 | type, flags, ¶ms); | 649 | type, flags, ¶ms); |
647 | 650 | ||
648 | dev = __dev_get_by_index(&init_net, ifindex); | 651 | dev = __dev_get_by_index(&init_net, ifindex); |
649 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); | 652 | WARN_ON(!dev || (!err && dev->ieee80211_ptr->iftype != type)); |
650 | 653 | ||
651 | rtnl_unlock(); | ||
652 | |||
653 | unlock: | 654 | unlock: |
654 | cfg80211_put_dev(drv); | 655 | cfg80211_put_dev(drv); |
656 | unlock_rtnl: | ||
657 | rtnl_unlock(); | ||
655 | return err; | 658 | return err; |
656 | } | 659 | } |
657 | 660 | ||
@@ -674,9 +677,13 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
674 | return -EINVAL; | 677 | return -EINVAL; |
675 | } | 678 | } |
676 | 679 | ||
680 | rtnl_lock(); | ||
681 | |||
677 | drv = cfg80211_get_dev_from_info(info); | 682 | drv = cfg80211_get_dev_from_info(info); |
678 | if (IS_ERR(drv)) | 683 | if (IS_ERR(drv)) { |
679 | return PTR_ERR(drv); | 684 | err = PTR_ERR(drv); |
685 | goto unlock_rtnl; | ||
686 | } | ||
680 | 687 | ||
681 | if (!drv->ops->add_virtual_intf || | 688 | if (!drv->ops->add_virtual_intf || |
682 | !(drv->wiphy.interface_modes & (1 << type))) { | 689 | !(drv->wiphy.interface_modes & (1 << type))) { |
@@ -690,18 +697,17 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
690 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); | 697 | params.mesh_id_len = nla_len(info->attrs[NL80211_ATTR_MESH_ID]); |
691 | } | 698 | } |
692 | 699 | ||
693 | rtnl_lock(); | ||
694 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? | 700 | err = parse_monitor_flags(type == NL80211_IFTYPE_MONITOR ? |
695 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, | 701 | info->attrs[NL80211_ATTR_MNTR_FLAGS] : NULL, |
696 | &flags); | 702 | &flags); |
697 | err = drv->ops->add_virtual_intf(&drv->wiphy, | 703 | err = drv->ops->add_virtual_intf(&drv->wiphy, |
698 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), | 704 | nla_data(info->attrs[NL80211_ATTR_IFNAME]), |
699 | type, err ? NULL : &flags, ¶ms); | 705 | type, err ? NULL : &flags, ¶ms); |
700 | rtnl_unlock(); | ||
701 | |||
702 | 706 | ||
703 | unlock: | 707 | unlock: |
704 | cfg80211_put_dev(drv); | 708 | cfg80211_put_dev(drv); |
709 | unlock_rtnl: | ||
710 | rtnl_unlock(); | ||
705 | return err; | 711 | return err; |
706 | } | 712 | } |
707 | 713 | ||
@@ -711,9 +717,11 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | |||
711 | int ifindex, err; | 717 | int ifindex, err; |
712 | struct net_device *dev; | 718 | struct net_device *dev; |
713 | 719 | ||
720 | rtnl_lock(); | ||
721 | |||
714 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 722 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
715 | if (err) | 723 | if (err) |
716 | return err; | 724 | goto unlock_rtnl; |
717 | ifindex = dev->ifindex; | 725 | ifindex = dev->ifindex; |
718 | dev_put(dev); | 726 | dev_put(dev); |
719 | 727 | ||
@@ -722,12 +730,12 @@ static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info) | |||
722 | goto out; | 730 | goto out; |
723 | } | 731 | } |
724 | 732 | ||
725 | rtnl_lock(); | ||
726 | err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); | 733 | err = drv->ops->del_virtual_intf(&drv->wiphy, ifindex); |
727 | rtnl_unlock(); | ||
728 | 734 | ||
729 | out: | 735 | out: |
730 | cfg80211_put_dev(drv); | 736 | cfg80211_put_dev(drv); |
737 | unlock_rtnl: | ||
738 | rtnl_unlock(); | ||
731 | return err; | 739 | return err; |
732 | } | 740 | } |
733 | 741 | ||
@@ -779,9 +787,11 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
779 | if (info->attrs[NL80211_ATTR_MAC]) | 787 | if (info->attrs[NL80211_ATTR_MAC]) |
780 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 788 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
781 | 789 | ||
790 | rtnl_lock(); | ||
791 | |||
782 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 792 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
783 | if (err) | 793 | if (err) |
784 | return err; | 794 | goto unlock_rtnl; |
785 | 795 | ||
786 | if (!drv->ops->get_key) { | 796 | if (!drv->ops->get_key) { |
787 | err = -EOPNOTSUPP; | 797 | err = -EOPNOTSUPP; |
@@ -809,10 +819,8 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
809 | if (mac_addr) | 819 | if (mac_addr) |
810 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); | 820 | NLA_PUT(msg, NL80211_ATTR_MAC, ETH_ALEN, mac_addr); |
811 | 821 | ||
812 | rtnl_lock(); | ||
813 | err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, | 822 | err = drv->ops->get_key(&drv->wiphy, dev, key_idx, mac_addr, |
814 | &cookie, get_key_callback); | 823 | &cookie, get_key_callback); |
815 | rtnl_unlock(); | ||
816 | 824 | ||
817 | if (err) | 825 | if (err) |
818 | goto out; | 826 | goto out; |
@@ -830,6 +838,9 @@ static int nl80211_get_key(struct sk_buff *skb, struct genl_info *info) | |||
830 | out: | 838 | out: |
831 | cfg80211_put_dev(drv); | 839 | cfg80211_put_dev(drv); |
832 | dev_put(dev); | 840 | dev_put(dev); |
841 | unlock_rtnl: | ||
842 | rtnl_unlock(); | ||
843 | |||
833 | return err; | 844 | return err; |
834 | } | 845 | } |
835 | 846 | ||
@@ -858,9 +869,11 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
858 | !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) | 869 | !info->attrs[NL80211_ATTR_KEY_DEFAULT_MGMT]) |
859 | return -EINVAL; | 870 | return -EINVAL; |
860 | 871 | ||
872 | rtnl_lock(); | ||
873 | |||
861 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 874 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
862 | if (err) | 875 | if (err) |
863 | return err; | 876 | goto unlock_rtnl; |
864 | 877 | ||
865 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) | 878 | if (info->attrs[NL80211_ATTR_KEY_DEFAULT]) |
866 | func = drv->ops->set_default_key; | 879 | func = drv->ops->set_default_key; |
@@ -872,13 +885,15 @@ static int nl80211_set_key(struct sk_buff *skb, struct genl_info *info) | |||
872 | goto out; | 885 | goto out; |
873 | } | 886 | } |
874 | 887 | ||
875 | rtnl_lock(); | ||
876 | err = func(&drv->wiphy, dev, key_idx); | 888 | err = func(&drv->wiphy, dev, key_idx); |
877 | rtnl_unlock(); | ||
878 | 889 | ||
879 | out: | 890 | out: |
880 | cfg80211_put_dev(drv); | 891 | cfg80211_put_dev(drv); |
881 | dev_put(dev); | 892 | dev_put(dev); |
893 | |||
894 | unlock_rtnl: | ||
895 | rtnl_unlock(); | ||
896 | |||
882 | return err; | 897 | return err; |
883 | } | 898 | } |
884 | 899 | ||
@@ -948,22 +963,25 @@ static int nl80211_new_key(struct sk_buff *skb, struct genl_info *info) | |||
948 | return -EINVAL; | 963 | return -EINVAL; |
949 | } | 964 | } |
950 | 965 | ||
966 | rtnl_lock(); | ||
967 | |||
951 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 968 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
952 | if (err) | 969 | if (err) |
953 | return err; | 970 | goto unlock_rtnl; |
954 | 971 | ||
955 | if (!drv->ops->add_key) { | 972 | if (!drv->ops->add_key) { |
956 | err = -EOPNOTSUPP; | 973 | err = -EOPNOTSUPP; |
957 | goto out; | 974 | goto out; |
958 | } | 975 | } |
959 | 976 | ||
960 | rtnl_lock(); | ||
961 | err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); | 977 | err = drv->ops->add_key(&drv->wiphy, dev, key_idx, mac_addr, ¶ms); |
962 | rtnl_unlock(); | ||
963 | 978 | ||
964 | out: | 979 | out: |
965 | cfg80211_put_dev(drv); | 980 | cfg80211_put_dev(drv); |
966 | dev_put(dev); | 981 | dev_put(dev); |
982 | unlock_rtnl: | ||
983 | rtnl_unlock(); | ||
984 | |||
967 | return err; | 985 | return err; |
968 | } | 986 | } |
969 | 987 | ||
@@ -984,22 +1002,26 @@ static int nl80211_del_key(struct sk_buff *skb, struct genl_info *info) | |||
984 | if (info->attrs[NL80211_ATTR_MAC]) | 1002 | if (info->attrs[NL80211_ATTR_MAC]) |
985 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1003 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
986 | 1004 | ||
1005 | rtnl_lock(); | ||
1006 | |||
987 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1007 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
988 | if (err) | 1008 | if (err) |
989 | return err; | 1009 | goto unlock_rtnl; |
990 | 1010 | ||
991 | if (!drv->ops->del_key) { | 1011 | if (!drv->ops->del_key) { |
992 | err = -EOPNOTSUPP; | 1012 | err = -EOPNOTSUPP; |
993 | goto out; | 1013 | goto out; |
994 | } | 1014 | } |
995 | 1015 | ||
996 | rtnl_lock(); | ||
997 | err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); | 1016 | err = drv->ops->del_key(&drv->wiphy, dev, key_idx, mac_addr); |
998 | rtnl_unlock(); | ||
999 | 1017 | ||
1000 | out: | 1018 | out: |
1001 | cfg80211_put_dev(drv); | 1019 | cfg80211_put_dev(drv); |
1002 | dev_put(dev); | 1020 | dev_put(dev); |
1021 | |||
1022 | unlock_rtnl: | ||
1023 | rtnl_unlock(); | ||
1024 | |||
1003 | return err; | 1025 | return err; |
1004 | } | 1026 | } |
1005 | 1027 | ||
@@ -1013,9 +1035,11 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1013 | struct beacon_parameters params; | 1035 | struct beacon_parameters params; |
1014 | int haveinfo = 0; | 1036 | int haveinfo = 0; |
1015 | 1037 | ||
1038 | rtnl_lock(); | ||
1039 | |||
1016 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1040 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1017 | if (err) | 1041 | if (err) |
1018 | return err; | 1042 | goto unlock_rtnl; |
1019 | 1043 | ||
1020 | switch (info->genlhdr->cmd) { | 1044 | switch (info->genlhdr->cmd) { |
1021 | case NL80211_CMD_NEW_BEACON: | 1045 | case NL80211_CMD_NEW_BEACON: |
@@ -1076,13 +1100,14 @@ static int nl80211_addset_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1076 | goto out; | 1100 | goto out; |
1077 | } | 1101 | } |
1078 | 1102 | ||
1079 | rtnl_lock(); | ||
1080 | err = call(&drv->wiphy, dev, ¶ms); | 1103 | err = call(&drv->wiphy, dev, ¶ms); |
1081 | rtnl_unlock(); | ||
1082 | 1104 | ||
1083 | out: | 1105 | out: |
1084 | cfg80211_put_dev(drv); | 1106 | cfg80211_put_dev(drv); |
1085 | dev_put(dev); | 1107 | dev_put(dev); |
1108 | unlock_rtnl: | ||
1109 | rtnl_unlock(); | ||
1110 | |||
1086 | return err; | 1111 | return err; |
1087 | } | 1112 | } |
1088 | 1113 | ||
@@ -1092,22 +1117,25 @@ static int nl80211_del_beacon(struct sk_buff *skb, struct genl_info *info) | |||
1092 | int err; | 1117 | int err; |
1093 | struct net_device *dev; | 1118 | struct net_device *dev; |
1094 | 1119 | ||
1120 | rtnl_lock(); | ||
1121 | |||
1095 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1122 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1096 | if (err) | 1123 | if (err) |
1097 | return err; | 1124 | goto unlock_rtnl; |
1098 | 1125 | ||
1099 | if (!drv->ops->del_beacon) { | 1126 | if (!drv->ops->del_beacon) { |
1100 | err = -EOPNOTSUPP; | 1127 | err = -EOPNOTSUPP; |
1101 | goto out; | 1128 | goto out; |
1102 | } | 1129 | } |
1103 | 1130 | ||
1104 | rtnl_lock(); | ||
1105 | err = drv->ops->del_beacon(&drv->wiphy, dev); | 1131 | err = drv->ops->del_beacon(&drv->wiphy, dev); |
1106 | rtnl_unlock(); | ||
1107 | 1132 | ||
1108 | out: | 1133 | out: |
1109 | cfg80211_put_dev(drv); | 1134 | cfg80211_put_dev(drv); |
1110 | dev_put(dev); | 1135 | dev_put(dev); |
1136 | unlock_rtnl: | ||
1137 | rtnl_unlock(); | ||
1138 | |||
1111 | return err; | 1139 | return err; |
1112 | } | 1140 | } |
1113 | 1141 | ||
@@ -1273,14 +1301,18 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
1273 | return -EINVAL; | 1301 | return -EINVAL; |
1274 | } | 1302 | } |
1275 | 1303 | ||
1276 | netdev = dev_get_by_index(&init_net, ifidx); | 1304 | rtnl_lock(); |
1277 | if (!netdev) | 1305 | |
1278 | return -ENODEV; | 1306 | netdev = __dev_get_by_index(&init_net, ifidx); |
1307 | if (!netdev) { | ||
1308 | err = -ENODEV; | ||
1309 | goto out_rtnl; | ||
1310 | } | ||
1279 | 1311 | ||
1280 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 1312 | dev = cfg80211_get_dev_from_ifindex(ifidx); |
1281 | if (IS_ERR(dev)) { | 1313 | if (IS_ERR(dev)) { |
1282 | err = PTR_ERR(dev); | 1314 | err = PTR_ERR(dev); |
1283 | goto out_put_netdev; | 1315 | goto out_rtnl; |
1284 | } | 1316 | } |
1285 | 1317 | ||
1286 | if (!dev->ops->dump_station) { | 1318 | if (!dev->ops->dump_station) { |
@@ -1288,15 +1320,13 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
1288 | goto out_err; | 1320 | goto out_err; |
1289 | } | 1321 | } |
1290 | 1322 | ||
1291 | rtnl_lock(); | ||
1292 | |||
1293 | while (1) { | 1323 | while (1) { |
1294 | err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, | 1324 | err = dev->ops->dump_station(&dev->wiphy, netdev, sta_idx, |
1295 | mac_addr, &sinfo); | 1325 | mac_addr, &sinfo); |
1296 | if (err == -ENOENT) | 1326 | if (err == -ENOENT) |
1297 | break; | 1327 | break; |
1298 | if (err) | 1328 | if (err) |
1299 | goto out_err_rtnl; | 1329 | goto out_err; |
1300 | 1330 | ||
1301 | if (nl80211_send_station(skb, | 1331 | if (nl80211_send_station(skb, |
1302 | NETLINK_CB(cb->skb).pid, | 1332 | NETLINK_CB(cb->skb).pid, |
@@ -1312,12 +1342,10 @@ static int nl80211_dump_station(struct sk_buff *skb, | |||
1312 | out: | 1342 | out: |
1313 | cb->args[1] = sta_idx; | 1343 | cb->args[1] = sta_idx; |
1314 | err = skb->len; | 1344 | err = skb->len; |
1315 | out_err_rtnl: | ||
1316 | rtnl_unlock(); | ||
1317 | out_err: | 1345 | out_err: |
1318 | cfg80211_put_dev(dev); | 1346 | cfg80211_put_dev(dev); |
1319 | out_put_netdev: | 1347 | out_rtnl: |
1320 | dev_put(netdev); | 1348 | rtnl_unlock(); |
1321 | 1349 | ||
1322 | return err; | 1350 | return err; |
1323 | } | 1351 | } |
@@ -1338,19 +1366,18 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
1338 | 1366 | ||
1339 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1367 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1340 | 1368 | ||
1369 | rtnl_lock(); | ||
1370 | |||
1341 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1371 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1342 | if (err) | 1372 | if (err) |
1343 | return err; | 1373 | goto out_rtnl; |
1344 | 1374 | ||
1345 | if (!drv->ops->get_station) { | 1375 | if (!drv->ops->get_station) { |
1346 | err = -EOPNOTSUPP; | 1376 | err = -EOPNOTSUPP; |
1347 | goto out; | 1377 | goto out; |
1348 | } | 1378 | } |
1349 | 1379 | ||
1350 | rtnl_lock(); | ||
1351 | err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); | 1380 | err = drv->ops->get_station(&drv->wiphy, dev, mac_addr, &sinfo); |
1352 | rtnl_unlock(); | ||
1353 | |||
1354 | if (err) | 1381 | if (err) |
1355 | goto out; | 1382 | goto out; |
1356 | 1383 | ||
@@ -1367,10 +1394,12 @@ static int nl80211_get_station(struct sk_buff *skb, struct genl_info *info) | |||
1367 | 1394 | ||
1368 | out_free: | 1395 | out_free: |
1369 | nlmsg_free(msg); | 1396 | nlmsg_free(msg); |
1370 | |||
1371 | out: | 1397 | out: |
1372 | cfg80211_put_dev(drv); | 1398 | cfg80211_put_dev(drv); |
1373 | dev_put(dev); | 1399 | dev_put(dev); |
1400 | out_rtnl: | ||
1401 | rtnl_unlock(); | ||
1402 | |||
1374 | return err; | 1403 | return err; |
1375 | } | 1404 | } |
1376 | 1405 | ||
@@ -1438,9 +1467,11 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1438 | params.plink_action = | 1467 | params.plink_action = |
1439 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); | 1468 | nla_get_u8(info->attrs[NL80211_ATTR_STA_PLINK_ACTION]); |
1440 | 1469 | ||
1470 | rtnl_lock(); | ||
1471 | |||
1441 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1472 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1442 | if (err) | 1473 | if (err) |
1443 | return err; | 1474 | goto out_rtnl; |
1444 | 1475 | ||
1445 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | 1476 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1446 | if (err) | 1477 | if (err) |
@@ -1451,15 +1482,16 @@ static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info) | |||
1451 | goto out; | 1482 | goto out; |
1452 | } | 1483 | } |
1453 | 1484 | ||
1454 | rtnl_lock(); | ||
1455 | err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); | 1485 | err = drv->ops->change_station(&drv->wiphy, dev, mac_addr, ¶ms); |
1456 | rtnl_unlock(); | ||
1457 | 1486 | ||
1458 | out: | 1487 | out: |
1459 | if (params.vlan) | 1488 | if (params.vlan) |
1460 | dev_put(params.vlan); | 1489 | dev_put(params.vlan); |
1461 | cfg80211_put_dev(drv); | 1490 | cfg80211_put_dev(drv); |
1462 | dev_put(dev); | 1491 | dev_put(dev); |
1492 | out_rtnl: | ||
1493 | rtnl_unlock(); | ||
1494 | |||
1463 | return err; | 1495 | return err; |
1464 | } | 1496 | } |
1465 | 1497 | ||
@@ -1501,9 +1533,11 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1501 | ¶ms.station_flags)) | 1533 | ¶ms.station_flags)) |
1502 | return -EINVAL; | 1534 | return -EINVAL; |
1503 | 1535 | ||
1536 | rtnl_lock(); | ||
1537 | |||
1504 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1538 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1505 | if (err) | 1539 | if (err) |
1506 | return err; | 1540 | goto out_rtnl; |
1507 | 1541 | ||
1508 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); | 1542 | err = get_vlan(info->attrs[NL80211_ATTR_STA_VLAN], drv, ¶ms.vlan); |
1509 | if (err) | 1543 | if (err) |
@@ -1514,15 +1548,16 @@ static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info) | |||
1514 | goto out; | 1548 | goto out; |
1515 | } | 1549 | } |
1516 | 1550 | ||
1517 | rtnl_lock(); | ||
1518 | err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); | 1551 | err = drv->ops->add_station(&drv->wiphy, dev, mac_addr, ¶ms); |
1519 | rtnl_unlock(); | ||
1520 | 1552 | ||
1521 | out: | 1553 | out: |
1522 | if (params.vlan) | 1554 | if (params.vlan) |
1523 | dev_put(params.vlan); | 1555 | dev_put(params.vlan); |
1524 | cfg80211_put_dev(drv); | 1556 | cfg80211_put_dev(drv); |
1525 | dev_put(dev); | 1557 | dev_put(dev); |
1558 | out_rtnl: | ||
1559 | rtnl_unlock(); | ||
1560 | |||
1526 | return err; | 1561 | return err; |
1527 | } | 1562 | } |
1528 | 1563 | ||
@@ -1536,22 +1571,25 @@ static int nl80211_del_station(struct sk_buff *skb, struct genl_info *info) | |||
1536 | if (info->attrs[NL80211_ATTR_MAC]) | 1571 | if (info->attrs[NL80211_ATTR_MAC]) |
1537 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1572 | mac_addr = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1538 | 1573 | ||
1574 | rtnl_lock(); | ||
1575 | |||
1539 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1576 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1540 | if (err) | 1577 | if (err) |
1541 | return err; | 1578 | goto out_rtnl; |
1542 | 1579 | ||
1543 | if (!drv->ops->del_station) { | 1580 | if (!drv->ops->del_station) { |
1544 | err = -EOPNOTSUPP; | 1581 | err = -EOPNOTSUPP; |
1545 | goto out; | 1582 | goto out; |
1546 | } | 1583 | } |
1547 | 1584 | ||
1548 | rtnl_lock(); | ||
1549 | err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); | 1585 | err = drv->ops->del_station(&drv->wiphy, dev, mac_addr); |
1550 | rtnl_unlock(); | ||
1551 | 1586 | ||
1552 | out: | 1587 | out: |
1553 | cfg80211_put_dev(drv); | 1588 | cfg80211_put_dev(drv); |
1554 | dev_put(dev); | 1589 | dev_put(dev); |
1590 | out_rtnl: | ||
1591 | rtnl_unlock(); | ||
1592 | |||
1555 | return err; | 1593 | return err; |
1556 | } | 1594 | } |
1557 | 1595 | ||
@@ -1632,14 +1670,18 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
1632 | return -EINVAL; | 1670 | return -EINVAL; |
1633 | } | 1671 | } |
1634 | 1672 | ||
1635 | netdev = dev_get_by_index(&init_net, ifidx); | 1673 | rtnl_lock(); |
1636 | if (!netdev) | 1674 | |
1637 | return -ENODEV; | 1675 | netdev = __dev_get_by_index(&init_net, ifidx); |
1676 | if (!netdev) { | ||
1677 | err = -ENODEV; | ||
1678 | goto out_rtnl; | ||
1679 | } | ||
1638 | 1680 | ||
1639 | dev = cfg80211_get_dev_from_ifindex(ifidx); | 1681 | dev = cfg80211_get_dev_from_ifindex(ifidx); |
1640 | if (IS_ERR(dev)) { | 1682 | if (IS_ERR(dev)) { |
1641 | err = PTR_ERR(dev); | 1683 | err = PTR_ERR(dev); |
1642 | goto out_put_netdev; | 1684 | goto out_rtnl; |
1643 | } | 1685 | } |
1644 | 1686 | ||
1645 | if (!dev->ops->dump_mpath) { | 1687 | if (!dev->ops->dump_mpath) { |
@@ -1647,15 +1689,13 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
1647 | goto out_err; | 1689 | goto out_err; |
1648 | } | 1690 | } |
1649 | 1691 | ||
1650 | rtnl_lock(); | ||
1651 | |||
1652 | while (1) { | 1692 | while (1) { |
1653 | err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, | 1693 | err = dev->ops->dump_mpath(&dev->wiphy, netdev, path_idx, |
1654 | dst, next_hop, &pinfo); | 1694 | dst, next_hop, &pinfo); |
1655 | if (err == -ENOENT) | 1695 | if (err == -ENOENT) |
1656 | break; | 1696 | break; |
1657 | if (err) | 1697 | if (err) |
1658 | goto out_err_rtnl; | 1698 | goto out_err; |
1659 | 1699 | ||
1660 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, | 1700 | if (nl80211_send_mpath(skb, NETLINK_CB(cb->skb).pid, |
1661 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | 1701 | cb->nlh->nlmsg_seq, NLM_F_MULTI, |
@@ -1670,12 +1710,10 @@ static int nl80211_dump_mpath(struct sk_buff *skb, | |||
1670 | out: | 1710 | out: |
1671 | cb->args[1] = path_idx; | 1711 | cb->args[1] = path_idx; |
1672 | err = skb->len; | 1712 | err = skb->len; |
1673 | out_err_rtnl: | ||
1674 | rtnl_unlock(); | ||
1675 | out_err: | 1713 | out_err: |
1676 | cfg80211_put_dev(dev); | 1714 | cfg80211_put_dev(dev); |
1677 | out_put_netdev: | 1715 | out_rtnl: |
1678 | dev_put(netdev); | 1716 | rtnl_unlock(); |
1679 | 1717 | ||
1680 | return err; | 1718 | return err; |
1681 | } | 1719 | } |
@@ -1697,19 +1735,18 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
1697 | 1735 | ||
1698 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1736 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1699 | 1737 | ||
1738 | rtnl_lock(); | ||
1739 | |||
1700 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1740 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1701 | if (err) | 1741 | if (err) |
1702 | return err; | 1742 | goto out_rtnl; |
1703 | 1743 | ||
1704 | if (!drv->ops->get_mpath) { | 1744 | if (!drv->ops->get_mpath) { |
1705 | err = -EOPNOTSUPP; | 1745 | err = -EOPNOTSUPP; |
1706 | goto out; | 1746 | goto out; |
1707 | } | 1747 | } |
1708 | 1748 | ||
1709 | rtnl_lock(); | ||
1710 | err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); | 1749 | err = drv->ops->get_mpath(&drv->wiphy, dev, dst, next_hop, &pinfo); |
1711 | rtnl_unlock(); | ||
1712 | |||
1713 | if (err) | 1750 | if (err) |
1714 | goto out; | 1751 | goto out; |
1715 | 1752 | ||
@@ -1726,10 +1763,12 @@ static int nl80211_get_mpath(struct sk_buff *skb, struct genl_info *info) | |||
1726 | 1763 | ||
1727 | out_free: | 1764 | out_free: |
1728 | nlmsg_free(msg); | 1765 | nlmsg_free(msg); |
1729 | |||
1730 | out: | 1766 | out: |
1731 | cfg80211_put_dev(drv); | 1767 | cfg80211_put_dev(drv); |
1732 | dev_put(dev); | 1768 | dev_put(dev); |
1769 | out_rtnl: | ||
1770 | rtnl_unlock(); | ||
1771 | |||
1733 | return err; | 1772 | return err; |
1734 | } | 1773 | } |
1735 | 1774 | ||
@@ -1750,22 +1789,25 @@ static int nl80211_set_mpath(struct sk_buff *skb, struct genl_info *info) | |||
1750 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1789 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1751 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 1790 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
1752 | 1791 | ||
1792 | rtnl_lock(); | ||
1793 | |||
1753 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1794 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1754 | if (err) | 1795 | if (err) |
1755 | return err; | 1796 | goto out_rtnl; |
1756 | 1797 | ||
1757 | if (!drv->ops->change_mpath) { | 1798 | if (!drv->ops->change_mpath) { |
1758 | err = -EOPNOTSUPP; | 1799 | err = -EOPNOTSUPP; |
1759 | goto out; | 1800 | goto out; |
1760 | } | 1801 | } |
1761 | 1802 | ||
1762 | rtnl_lock(); | ||
1763 | err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); | 1803 | err = drv->ops->change_mpath(&drv->wiphy, dev, dst, next_hop); |
1764 | rtnl_unlock(); | ||
1765 | 1804 | ||
1766 | out: | 1805 | out: |
1767 | cfg80211_put_dev(drv); | 1806 | cfg80211_put_dev(drv); |
1768 | dev_put(dev); | 1807 | dev_put(dev); |
1808 | out_rtnl: | ||
1809 | rtnl_unlock(); | ||
1810 | |||
1769 | return err; | 1811 | return err; |
1770 | } | 1812 | } |
1771 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | 1813 | static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) |
@@ -1785,22 +1827,25 @@ static int nl80211_new_mpath(struct sk_buff *skb, struct genl_info *info) | |||
1785 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1827 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1786 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); | 1828 | next_hop = nla_data(info->attrs[NL80211_ATTR_MPATH_NEXT_HOP]); |
1787 | 1829 | ||
1830 | rtnl_lock(); | ||
1831 | |||
1788 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1832 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1789 | if (err) | 1833 | if (err) |
1790 | return err; | 1834 | goto out_rtnl; |
1791 | 1835 | ||
1792 | if (!drv->ops->add_mpath) { | 1836 | if (!drv->ops->add_mpath) { |
1793 | err = -EOPNOTSUPP; | 1837 | err = -EOPNOTSUPP; |
1794 | goto out; | 1838 | goto out; |
1795 | } | 1839 | } |
1796 | 1840 | ||
1797 | rtnl_lock(); | ||
1798 | err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); | 1841 | err = drv->ops->add_mpath(&drv->wiphy, dev, dst, next_hop); |
1799 | rtnl_unlock(); | ||
1800 | 1842 | ||
1801 | out: | 1843 | out: |
1802 | cfg80211_put_dev(drv); | 1844 | cfg80211_put_dev(drv); |
1803 | dev_put(dev); | 1845 | dev_put(dev); |
1846 | out_rtnl: | ||
1847 | rtnl_unlock(); | ||
1848 | |||
1804 | return err; | 1849 | return err; |
1805 | } | 1850 | } |
1806 | 1851 | ||
@@ -1814,22 +1859,25 @@ static int nl80211_del_mpath(struct sk_buff *skb, struct genl_info *info) | |||
1814 | if (info->attrs[NL80211_ATTR_MAC]) | 1859 | if (info->attrs[NL80211_ATTR_MAC]) |
1815 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); | 1860 | dst = nla_data(info->attrs[NL80211_ATTR_MAC]); |
1816 | 1861 | ||
1862 | rtnl_lock(); | ||
1863 | |||
1817 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1864 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1818 | if (err) | 1865 | if (err) |
1819 | return err; | 1866 | goto out_rtnl; |
1820 | 1867 | ||
1821 | if (!drv->ops->del_mpath) { | 1868 | if (!drv->ops->del_mpath) { |
1822 | err = -EOPNOTSUPP; | 1869 | err = -EOPNOTSUPP; |
1823 | goto out; | 1870 | goto out; |
1824 | } | 1871 | } |
1825 | 1872 | ||
1826 | rtnl_lock(); | ||
1827 | err = drv->ops->del_mpath(&drv->wiphy, dev, dst); | 1873 | err = drv->ops->del_mpath(&drv->wiphy, dev, dst); |
1828 | rtnl_unlock(); | ||
1829 | 1874 | ||
1830 | out: | 1875 | out: |
1831 | cfg80211_put_dev(drv); | 1876 | cfg80211_put_dev(drv); |
1832 | dev_put(dev); | 1877 | dev_put(dev); |
1878 | out_rtnl: | ||
1879 | rtnl_unlock(); | ||
1880 | |||
1833 | return err; | 1881 | return err; |
1834 | } | 1882 | } |
1835 | 1883 | ||
@@ -1862,22 +1910,25 @@ static int nl80211_set_bss(struct sk_buff *skb, struct genl_info *info) | |||
1862 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); | 1910 | nla_len(info->attrs[NL80211_ATTR_BSS_BASIC_RATES]); |
1863 | } | 1911 | } |
1864 | 1912 | ||
1913 | rtnl_lock(); | ||
1914 | |||
1865 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 1915 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1866 | if (err) | 1916 | if (err) |
1867 | return err; | 1917 | goto out_rtnl; |
1868 | 1918 | ||
1869 | if (!drv->ops->change_bss) { | 1919 | if (!drv->ops->change_bss) { |
1870 | err = -EOPNOTSUPP; | 1920 | err = -EOPNOTSUPP; |
1871 | goto out; | 1921 | goto out; |
1872 | } | 1922 | } |
1873 | 1923 | ||
1874 | rtnl_lock(); | ||
1875 | err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); | 1924 | err = drv->ops->change_bss(&drv->wiphy, dev, ¶ms); |
1876 | rtnl_unlock(); | ||
1877 | 1925 | ||
1878 | out: | 1926 | out: |
1879 | cfg80211_put_dev(drv); | 1927 | cfg80211_put_dev(drv); |
1880 | dev_put(dev); | 1928 | dev_put(dev); |
1929 | out_rtnl: | ||
1930 | rtnl_unlock(); | ||
1931 | |||
1881 | return err; | 1932 | return err; |
1882 | } | 1933 | } |
1883 | 1934 | ||
@@ -1972,10 +2023,12 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
1972 | struct nlattr *pinfoattr; | 2023 | struct nlattr *pinfoattr; |
1973 | struct sk_buff *msg; | 2024 | struct sk_buff *msg; |
1974 | 2025 | ||
2026 | rtnl_lock(); | ||
2027 | |||
1975 | /* Look up our device */ | 2028 | /* Look up our device */ |
1976 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 2029 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
1977 | if (err) | 2030 | if (err) |
1978 | return err; | 2031 | goto out_rtnl; |
1979 | 2032 | ||
1980 | if (!drv->ops->get_mesh_params) { | 2033 | if (!drv->ops->get_mesh_params) { |
1981 | err = -EOPNOTSUPP; | 2034 | err = -EOPNOTSUPP; |
@@ -1983,9 +2036,7 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
1983 | } | 2036 | } |
1984 | 2037 | ||
1985 | /* Get the mesh params */ | 2038 | /* Get the mesh params */ |
1986 | rtnl_lock(); | ||
1987 | err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); | 2039 | err = drv->ops->get_mesh_params(&drv->wiphy, dev, &cur_params); |
1988 | rtnl_unlock(); | ||
1989 | if (err) | 2040 | if (err) |
1990 | goto out; | 2041 | goto out; |
1991 | 2042 | ||
@@ -2034,13 +2085,16 @@ static int nl80211_get_mesh_params(struct sk_buff *skb, | |||
2034 | err = genlmsg_unicast(msg, info->snd_pid); | 2085 | err = genlmsg_unicast(msg, info->snd_pid); |
2035 | goto out; | 2086 | goto out; |
2036 | 2087 | ||
2037 | nla_put_failure: | 2088 | nla_put_failure: |
2038 | genlmsg_cancel(msg, hdr); | 2089 | genlmsg_cancel(msg, hdr); |
2039 | err = -EMSGSIZE; | 2090 | err = -EMSGSIZE; |
2040 | out: | 2091 | out: |
2041 | /* Cleanup */ | 2092 | /* Cleanup */ |
2042 | cfg80211_put_dev(drv); | 2093 | cfg80211_put_dev(drv); |
2043 | dev_put(dev); | 2094 | dev_put(dev); |
2095 | out_rtnl: | ||
2096 | rtnl_unlock(); | ||
2097 | |||
2044 | return err; | 2098 | return err; |
2045 | } | 2099 | } |
2046 | 2100 | ||
@@ -2087,9 +2141,11 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2087 | parent_attr, nl80211_meshconf_params_policy)) | 2141 | parent_attr, nl80211_meshconf_params_policy)) |
2088 | return -EINVAL; | 2142 | return -EINVAL; |
2089 | 2143 | ||
2144 | rtnl_lock(); | ||
2145 | |||
2090 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 2146 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
2091 | if (err) | 2147 | if (err) |
2092 | return err; | 2148 | goto out_rtnl; |
2093 | 2149 | ||
2094 | if (!drv->ops->set_mesh_params) { | 2150 | if (!drv->ops->set_mesh_params) { |
2095 | err = -EOPNOTSUPP; | 2151 | err = -EOPNOTSUPP; |
@@ -2136,14 +2192,15 @@ static int nl80211_set_mesh_params(struct sk_buff *skb, struct genl_info *info) | |||
2136 | nla_get_u16); | 2192 | nla_get_u16); |
2137 | 2193 | ||
2138 | /* Apply changes */ | 2194 | /* Apply changes */ |
2139 | rtnl_lock(); | ||
2140 | err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); | 2195 | err = drv->ops->set_mesh_params(&drv->wiphy, dev, &cfg, mask); |
2141 | rtnl_unlock(); | ||
2142 | 2196 | ||
2143 | out: | 2197 | out: |
2144 | /* cleanup */ | 2198 | /* cleanup */ |
2145 | cfg80211_put_dev(drv); | 2199 | cfg80211_put_dev(drv); |
2146 | dev_put(dev); | 2200 | dev_put(dev); |
2201 | out_rtnl: | ||
2202 | rtnl_unlock(); | ||
2203 | |||
2147 | return err; | 2204 | return err; |
2148 | } | 2205 | } |
2149 | 2206 | ||
@@ -2310,19 +2367,22 @@ static int nl80211_set_mgmt_extra_ie(struct sk_buff *skb, | |||
2310 | params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 2367 | params.ies_len = nla_len(info->attrs[NL80211_ATTR_IE]); |
2311 | } | 2368 | } |
2312 | 2369 | ||
2370 | rtnl_lock(); | ||
2371 | |||
2313 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 2372 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
2314 | if (err) | 2373 | if (err) |
2315 | return err; | 2374 | goto out_rtnl; |
2316 | 2375 | ||
2317 | if (drv->ops->set_mgmt_extra_ie) { | 2376 | if (drv->ops->set_mgmt_extra_ie) |
2318 | rtnl_lock(); | ||
2319 | err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); | 2377 | err = drv->ops->set_mgmt_extra_ie(&drv->wiphy, dev, ¶ms); |
2320 | rtnl_unlock(); | 2378 | else |
2321 | } else | ||
2322 | err = -EOPNOTSUPP; | 2379 | err = -EOPNOTSUPP; |
2323 | 2380 | ||
2324 | cfg80211_put_dev(drv); | 2381 | cfg80211_put_dev(drv); |
2325 | dev_put(dev); | 2382 | dev_put(dev); |
2383 | out_rtnl: | ||
2384 | rtnl_unlock(); | ||
2385 | |||
2326 | return err; | 2386 | return err; |
2327 | } | 2387 | } |
2328 | 2388 | ||
@@ -2339,9 +2399,11 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2339 | enum ieee80211_band band; | 2399 | enum ieee80211_band band; |
2340 | size_t ie_len; | 2400 | size_t ie_len; |
2341 | 2401 | ||
2402 | rtnl_lock(); | ||
2403 | |||
2342 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); | 2404 | err = get_drv_dev_by_info_ifindex(info->attrs, &drv, &dev); |
2343 | if (err) | 2405 | if (err) |
2344 | return err; | 2406 | goto out_rtnl; |
2345 | 2407 | ||
2346 | wiphy = &drv->wiphy; | 2408 | wiphy = &drv->wiphy; |
2347 | 2409 | ||
@@ -2350,11 +2412,9 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2350 | goto out; | 2412 | goto out; |
2351 | } | 2413 | } |
2352 | 2414 | ||
2353 | rtnl_lock(); | ||
2354 | |||
2355 | if (drv->scan_req) { | 2415 | if (drv->scan_req) { |
2356 | err = -EBUSY; | 2416 | err = -EBUSY; |
2357 | goto out_unlock; | 2417 | goto out; |
2358 | } | 2418 | } |
2359 | 2419 | ||
2360 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { | 2420 | if (info->attrs[NL80211_ATTR_SCAN_FREQUENCIES]) { |
@@ -2362,7 +2422,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2362 | n_channels++; | 2422 | n_channels++; |
2363 | if (!n_channels) { | 2423 | if (!n_channels) { |
2364 | err = -EINVAL; | 2424 | err = -EINVAL; |
2365 | goto out_unlock; | 2425 | goto out; |
2366 | } | 2426 | } |
2367 | } else { | 2427 | } else { |
2368 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) | 2428 | for (band = 0; band < IEEE80211_NUM_BANDS; band++) |
@@ -2376,7 +2436,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2376 | 2436 | ||
2377 | if (n_ssids > wiphy->max_scan_ssids) { | 2437 | if (n_ssids > wiphy->max_scan_ssids) { |
2378 | err = -EINVAL; | 2438 | err = -EINVAL; |
2379 | goto out_unlock; | 2439 | goto out; |
2380 | } | 2440 | } |
2381 | 2441 | ||
2382 | if (info->attrs[NL80211_ATTR_IE]) | 2442 | if (info->attrs[NL80211_ATTR_IE]) |
@@ -2390,7 +2450,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2390 | + ie_len, GFP_KERNEL); | 2450 | + ie_len, GFP_KERNEL); |
2391 | if (!request) { | 2451 | if (!request) { |
2392 | err = -ENOMEM; | 2452 | err = -ENOMEM; |
2393 | goto out_unlock; | 2453 | goto out; |
2394 | } | 2454 | } |
2395 | 2455 | ||
2396 | request->channels = (void *)((char *)request + sizeof(*request)); | 2456 | request->channels = (void *)((char *)request + sizeof(*request)); |
@@ -2461,11 +2521,12 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
2461 | drv->scan_req = NULL; | 2521 | drv->scan_req = NULL; |
2462 | kfree(request); | 2522 | kfree(request); |
2463 | } | 2523 | } |
2464 | out_unlock: | ||
2465 | rtnl_unlock(); | ||
2466 | out: | 2524 | out: |
2467 | cfg80211_put_dev(drv); | 2525 | cfg80211_put_dev(drv); |
2468 | dev_put(dev); | 2526 | dev_put(dev); |
2527 | out_rtnl: | ||
2528 | rtnl_unlock(); | ||
2529 | |||
2469 | return err; | 2530 | return err; |
2470 | } | 2531 | } |
2471 | 2532 | ||