aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r--net/wireless/util.c21
1 files changed, 19 insertions, 2 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 55d99466babb..316cfd00914f 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -804,7 +804,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
804 ntype == NL80211_IFTYPE_P2P_CLIENT)) 804 ntype == NL80211_IFTYPE_P2P_CLIENT))
805 return -EBUSY; 805 return -EBUSY;
806 806
807 if (ntype != otype) { 807 if (ntype != otype && netif_running(dev)) {
808 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr, 808 err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
809 ntype); 809 ntype);
810 if (err) 810 if (err)
@@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
935 enum nl80211_iftype iftype) 935 enum nl80211_iftype iftype)
936{ 936{
937 struct wireless_dev *wdev_iter; 937 struct wireless_dev *wdev_iter;
938 u32 used_iftypes = BIT(iftype);
938 int num[NUM_NL80211_IFTYPES]; 939 int num[NUM_NL80211_IFTYPES];
939 int total = 1; 940 int total = 1;
940 int i, j; 941 int i, j;
@@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
961 962
962 num[wdev_iter->iftype]++; 963 num[wdev_iter->iftype]++;
963 total++; 964 total++;
965 used_iftypes |= BIT(wdev_iter->iftype);
964 } 966 }
965 mutex_unlock(&rdev->devlist_mtx); 967 mutex_unlock(&rdev->devlist_mtx);
966 968
@@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
970 for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { 972 for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {
971 const struct ieee80211_iface_combination *c; 973 const struct ieee80211_iface_combination *c;
972 struct ieee80211_iface_limit *limits; 974 struct ieee80211_iface_limit *limits;
975 u32 all_iftypes = 0;
973 976
974 c = &rdev->wiphy.iface_combinations[i]; 977 c = &rdev->wiphy.iface_combinations[i];
975 978
@@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
984 if (rdev->wiphy.software_iftypes & BIT(iftype)) 987 if (rdev->wiphy.software_iftypes & BIT(iftype))
985 continue; 988 continue;
986 for (j = 0; j < c->n_limits; j++) { 989 for (j = 0; j < c->n_limits; j++) {
990 all_iftypes |= limits[j].types;
987 if (!(limits[j].types & BIT(iftype))) 991 if (!(limits[j].types & BIT(iftype)))
988 continue; 992 continue;
989 if (limits[j].max < num[iftype]) 993 if (limits[j].max < num[iftype])
@@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
991 limits[j].max -= num[iftype]; 995 limits[j].max -= num[iftype];
992 } 996 }
993 } 997 }
994 /* yay, it fits */ 998
999 /*
1000 * Finally check that all iftypes that we're currently
1001 * using are actually part of this combination. If they
1002 * aren't then we can't use this combination and have
1003 * to continue to the next.
1004 */
1005 if ((all_iftypes & used_iftypes) != used_iftypes)
1006 goto cont;
1007
1008 /*
1009 * This combination covered all interface types and
1010 * supported the requested numbers, so we're good.
1011 */
995 kfree(limits); 1012 kfree(limits);
996 return 0; 1013 return 0;
997 cont: 1014 cont: