Merge tag 'staging-6.0-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh...
[linux-2.6-microblaze.git] / net / wireless / reg.c
index 58e83ce..c7383ed 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2008-2011 Luis R. Rodriguez <mcgrof@qca.qualcomm.com>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright      2017  Intel Deutschland GmbH
- * Copyright (C) 2018 - 2021 Intel Corporation
+ * Copyright (C) 2018 - 2022 Intel Corporation
  *
  * Permission to use, copy, modify, and/or distribute this software for any
  * purpose with or without fee is hereby granted, provided that the above
@@ -2370,6 +2370,7 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
        enum nl80211_iftype iftype;
        bool ret;
+       int link;
 
        wdev_lock(wdev);
        iftype = wdev->iftype;
@@ -2378,62 +2379,83 @@ static bool reg_wdev_chan_valid(struct wiphy *wiphy, struct wireless_dev *wdev)
        if (!wdev->netdev || !netif_running(wdev->netdev))
                goto wdev_inactive_unlock;
 
-       switch (iftype) {
-       case NL80211_IFTYPE_AP:
-       case NL80211_IFTYPE_P2P_GO:
-       case NL80211_IFTYPE_MESH_POINT:
-               if (!wdev->beacon_interval)
-                       goto wdev_inactive_unlock;
-               chandef = wdev->chandef;
-               break;
-       case NL80211_IFTYPE_ADHOC:
-               if (!wdev->ssid_len)
-                       goto wdev_inactive_unlock;
-               chandef = wdev->chandef;
-               break;
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_P2P_CLIENT:
-               if (!wdev->current_bss ||
-                   !wdev->current_bss->pub.channel)
-                       goto wdev_inactive_unlock;
-
-               if (!rdev->ops->get_channel ||
-                   rdev_get_channel(rdev, wdev, &chandef))
-                       cfg80211_chandef_create(&chandef,
-                                               wdev->current_bss->pub.channel,
-                                               NL80211_CHAN_NO_HT);
-               break;
-       case NL80211_IFTYPE_MONITOR:
-       case NL80211_IFTYPE_AP_VLAN:
-       case NL80211_IFTYPE_P2P_DEVICE:
-               /* no enforcement required */
-               break;
-       default:
-               /* others not implemented for now */
-               WARN_ON(1);
-               break;
-       }
+       for (link = 0; link < ARRAY_SIZE(wdev->links); link++) {
+               struct ieee80211_channel *chan;
 
-       wdev_unlock(wdev);
+               if (!wdev->valid_links && link > 0)
+                       break;
+               if (!(wdev->valid_links & BIT(link)))
+                       continue;
+               switch (iftype) {
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_P2P_GO:
+               case NL80211_IFTYPE_MESH_POINT:
+                       if (!wdev->u.mesh.beacon_interval)
+                               continue;
+                       chandef = wdev->u.mesh.chandef;
+                       break;
+               case NL80211_IFTYPE_ADHOC:
+                       if (!wdev->u.ibss.ssid_len)
+                               continue;
+                       chandef = wdev->u.ibss.chandef;
+                       break;
+               case NL80211_IFTYPE_STATION:
+               case NL80211_IFTYPE_P2P_CLIENT:
+                       /* Maybe we could consider disabling that link only? */
+                       if (!wdev->links[link].client.current_bss)
+                               continue;
 
-       switch (iftype) {
-       case NL80211_IFTYPE_AP:
-       case NL80211_IFTYPE_P2P_GO:
-       case NL80211_IFTYPE_ADHOC:
-       case NL80211_IFTYPE_MESH_POINT:
-               wiphy_lock(wiphy);
-               ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef, iftype);
-               wiphy_unlock(wiphy);
+                       chan = wdev->links[link].client.current_bss->pub.channel;
+                       if (!chan)
+                               continue;
 
-               return ret;
-       case NL80211_IFTYPE_STATION:
-       case NL80211_IFTYPE_P2P_CLIENT:
-               return cfg80211_chandef_usable(wiphy, &chandef,
-                                              IEEE80211_CHAN_DISABLED);
-       default:
-               break;
+                       if (!rdev->ops->get_channel ||
+                           rdev_get_channel(rdev, wdev, link, &chandef))
+                               cfg80211_chandef_create(&chandef, chan,
+                                                       NL80211_CHAN_NO_HT);
+                       break;
+               case NL80211_IFTYPE_MONITOR:
+               case NL80211_IFTYPE_AP_VLAN:
+               case NL80211_IFTYPE_P2P_DEVICE:
+                       /* no enforcement required */
+                       break;
+               default:
+                       /* others not implemented for now */
+                       WARN_ON(1);
+                       break;
+               }
+
+               wdev_unlock(wdev);
+
+               switch (iftype) {
+               case NL80211_IFTYPE_AP:
+               case NL80211_IFTYPE_P2P_GO:
+               case NL80211_IFTYPE_ADHOC:
+               case NL80211_IFTYPE_MESH_POINT:
+                       wiphy_lock(wiphy);
+                       ret = cfg80211_reg_can_beacon_relax(wiphy, &chandef,
+                                                           iftype);
+                       wiphy_unlock(wiphy);
+
+                       if (!ret)
+                               return ret;
+                       break;
+               case NL80211_IFTYPE_STATION:
+               case NL80211_IFTYPE_P2P_CLIENT:
+                       ret = cfg80211_chandef_usable(wiphy, &chandef,
+                                                     IEEE80211_CHAN_DISABLED);
+                       if (!ret)
+                               return ret;
+                       break;
+               default:
+                       break;
+               }
+
+               wdev_lock(wdev);
        }
 
+       wdev_unlock(wdev);
+
        return true;
 
 wdev_inactive_unlock:
@@ -4215,8 +4237,17 @@ static void cfg80211_check_and_end_cac(struct cfg80211_registered_device *rdev)
         * In both cases we should end the CAC on the wdev.
         */
        list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
-               if (wdev->cac_started &&
-                   !cfg80211_chandef_dfs_usable(&rdev->wiphy, &wdev->chandef))
+               struct cfg80211_chan_def *chandef;
+
+               if (!wdev->cac_started)
+                       continue;
+
+               /* FIXME: radar detection is tied to link 0 for now */
+               chandef = wdev_chandef(wdev, 0);
+               if (!chandef)
+                       continue;
+
+               if (!cfg80211_chandef_dfs_usable(&rdev->wiphy, chandef))
                        rdev_end_cac(rdev, wdev->netdev);
        }
 }