diff options
Diffstat (limited to 'net/wireless/util.c')
-rw-r--r-- | net/wireless/util.c | 42 |
1 files changed, 39 insertions, 3 deletions
diff --git a/net/wireless/util.c b/net/wireless/util.c index 16d76a807c2f..37a56ee1e1ed 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -1184,7 +1184,8 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1184 | struct wireless_dev *wdev, | 1184 | struct wireless_dev *wdev, |
1185 | enum nl80211_iftype iftype, | 1185 | enum nl80211_iftype iftype, |
1186 | struct ieee80211_channel *chan, | 1186 | struct ieee80211_channel *chan, |
1187 | enum cfg80211_chan_mode chanmode) | 1187 | enum cfg80211_chan_mode chanmode, |
1188 | u8 radar_detect) | ||
1188 | { | 1189 | { |
1189 | struct wireless_dev *wdev_iter; | 1190 | struct wireless_dev *wdev_iter; |
1190 | u32 used_iftypes = BIT(iftype); | 1191 | u32 used_iftypes = BIT(iftype); |
@@ -1195,14 +1196,46 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1195 | enum cfg80211_chan_mode chmode; | 1196 | enum cfg80211_chan_mode chmode; |
1196 | int num_different_channels = 0; | 1197 | int num_different_channels = 0; |
1197 | int total = 1; | 1198 | int total = 1; |
1199 | bool radar_required; | ||
1198 | int i, j; | 1200 | int i, j; |
1199 | 1201 | ||
1200 | ASSERT_RTNL(); | 1202 | ASSERT_RTNL(); |
1201 | lockdep_assert_held(&rdev->devlist_mtx); | 1203 | lockdep_assert_held(&rdev->devlist_mtx); |
1202 | 1204 | ||
1205 | if (WARN_ON(hweight32(radar_detect) > 1)) | ||
1206 | return -EINVAL; | ||
1207 | |||
1208 | switch (iftype) { | ||
1209 | case NL80211_IFTYPE_ADHOC: | ||
1210 | case NL80211_IFTYPE_AP: | ||
1211 | case NL80211_IFTYPE_AP_VLAN: | ||
1212 | case NL80211_IFTYPE_MESH_POINT: | ||
1213 | case NL80211_IFTYPE_P2P_GO: | ||
1214 | case NL80211_IFTYPE_WDS: | ||
1215 | radar_required = !!(chan && | ||
1216 | (chan->flags & IEEE80211_CHAN_RADAR)); | ||
1217 | break; | ||
1218 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1219 | case NL80211_IFTYPE_STATION: | ||
1220 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1221 | case NL80211_IFTYPE_MONITOR: | ||
1222 | radar_required = false; | ||
1223 | break; | ||
1224 | case NUM_NL80211_IFTYPES: | ||
1225 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1226 | default: | ||
1227 | return -EINVAL; | ||
1228 | } | ||
1229 | |||
1230 | if (radar_required && !radar_detect) | ||
1231 | return -EINVAL; | ||
1232 | |||
1203 | /* Always allow software iftypes */ | 1233 | /* Always allow software iftypes */ |
1204 | if (rdev->wiphy.software_iftypes & BIT(iftype)) | 1234 | if (rdev->wiphy.software_iftypes & BIT(iftype)) { |
1235 | if (radar_detect) | ||
1236 | return -EINVAL; | ||
1205 | return 0; | 1237 | return 0; |
1238 | } | ||
1206 | 1239 | ||
1207 | memset(num, 0, sizeof(num)); | 1240 | memset(num, 0, sizeof(num)); |
1208 | memset(used_channels, 0, sizeof(used_channels)); | 1241 | memset(used_channels, 0, sizeof(used_channels)); |
@@ -1275,7 +1308,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1275 | used_iftypes |= BIT(wdev_iter->iftype); | 1308 | used_iftypes |= BIT(wdev_iter->iftype); |
1276 | } | 1309 | } |
1277 | 1310 | ||
1278 | if (total == 1) | 1311 | if (total == 1 && !radar_detect) |
1279 | return 0; | 1312 | return 0; |
1280 | 1313 | ||
1281 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { | 1314 | for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) { |
@@ -1308,6 +1341,9 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1308 | } | 1341 | } |
1309 | } | 1342 | } |
1310 | 1343 | ||
1344 | if (radar_detect && !(c->radar_detect_widths & radar_detect)) | ||
1345 | goto cont; | ||
1346 | |||
1311 | /* | 1347 | /* |
1312 | * Finally check that all iftypes that we're currently | 1348 | * Finally check that all iftypes that we're currently |
1313 | * using are actually part of this combination. If they | 1349 | * using are actually part of this combination. If they |