cfg80211: Add a function to get the number of supported channels
[firefly-linux-kernel-4.4.55.git] / net / wireless / util.c
index 3c8be6104ba407a9d0b5d997d8c2fe4d659a63e4..d39c37104ae2f125c5def9c943dc65ab8a669f5a 100644 (file)
@@ -689,7 +689,8 @@ void ieee80211_amsdu_to_8023s(struct sk_buff *skb, struct sk_buff_head *list,
 EXPORT_SYMBOL(ieee80211_amsdu_to_8023s);
 
 /* Given a data frame determine the 802.1p/1d tag to use. */
-unsigned int cfg80211_classify8021d(struct sk_buff *skb)
+unsigned int cfg80211_classify8021d(struct sk_buff *skb,
+                                   struct cfg80211_qos_map *qos_map)
 {
        unsigned int dscp;
        unsigned char vlan_priority;
@@ -720,6 +721,21 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb)
                return 0;
        }
 
+       if (qos_map) {
+               unsigned int i, tmp_dscp = dscp >> 2;
+
+               for (i = 0; i < qos_map->num_des; i++) {
+                       if (tmp_dscp == qos_map->dscp_exception[i].dscp)
+                               return qos_map->dscp_exception[i].up;
+               }
+
+               for (i = 0; i < 8; i++) {
+                       if (tmp_dscp >= qos_map->up[i].low &&
+                           tmp_dscp <= qos_map->up[i].high)
+                               return i;
+               }
+       }
+
        return dscp >> 5;
 }
 EXPORT_SYMBOL(cfg80211_classify8021d);
@@ -863,6 +879,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
 
                dev->ieee80211_ptr->use_4addr = false;
                dev->ieee80211_ptr->mesh_id_up_len = 0;
+               wdev_lock(dev->ieee80211_ptr);
+               rdev_set_qos_map(rdev, dev, NULL);
+               wdev_unlock(dev->ieee80211_ptr);
 
                switch (otype) {
                case NL80211_IFTYPE_AP:
@@ -1249,7 +1268,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
        enum cfg80211_chan_mode chmode;
        int num_different_channels = 0;
        int total = 1;
-       bool radar_required;
+       bool radar_required = false;
        int i, j;
 
        ASSERT_RTNL();
@@ -1264,14 +1283,20 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev,
        case NL80211_IFTYPE_MESH_POINT:
        case NL80211_IFTYPE_P2P_GO:
        case NL80211_IFTYPE_WDS:
-               radar_required = !!(chan &&
-                                   (chan->flags & IEEE80211_CHAN_RADAR));
+               /* if the interface could potentially choose a DFS channel,
+                * then mark DFS as required.
+                */
+               if (!chan) {
+                       if (chanmode != CHAN_MODE_UNDEFINED && radar_detect)
+                               radar_required = true;
+                       break;
+               }
+               radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR);
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
        case NL80211_IFTYPE_P2P_DEVICE:
        case NL80211_IFTYPE_MONITOR:
-               radar_required = false;
                break;
        case NUM_NL80211_IFTYPES:
        case NL80211_IFTYPE_UNSPECIFIED:
@@ -1456,6 +1481,19 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
        return 0;
 }
 
+unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy)
+{
+       enum ieee80211_band band;
+       unsigned int n_channels = 0;
+
+       for (band = 0; band < IEEE80211_NUM_BANDS; band++)
+               if (wiphy->bands[band])
+                       n_channels += wiphy->bands[band]->n_channels;
+
+       return n_channels;
+}
+EXPORT_SYMBOL(ieee80211_get_num_supported_channels);
+
 /* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
 /* Ethernet-II snap header (RFC1042 for most EtherTypes) */
 const unsigned char rfc1042_header[] __aligned(2) =