cfg80211/mac80211: move more combination checks to mac80211
authorLuciano Coelho <luciano.coelho@intel.com>
Thu, 27 Feb 2014 09:07:21 +0000 (11:07 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 9 Apr 2014 08:55:47 +0000 (10:55 +0200)
Get rid of the cfg80211_can_add_interface() and
cfg80211_can_change_interface() functions by moving that functionality
to mac80211.  With this patch all interface combination checks are now
out of cfg80211 (except for the channel switch case which will be
addressed in a future commit).

Additionally, modify the ieee80211_check_combinations() function so
that an undefined chandef can be passed, in order to use it before a
channel is defined.

Signed-off-by: Luciano Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c
net/mac80211/iface.c
net/mac80211/util.c
net/wireless/core.c
net/wireless/core.h
net/wireless/nl80211.c
net/wireless/util.c

index 8bf94eaa0456e281113cf14f422cc7e36021905f..23d60110aebdec57b92c67bbc0ecad2e761654ce 100644 (file)
@@ -109,6 +109,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
 static int ieee80211_start_p2p_device(struct wiphy *wiphy,
                                      struct wireless_dev *wdev)
 {
+       struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+       int ret;
+
+       mutex_lock(&sdata->local->chanctx_mtx);
+       ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
+       mutex_unlock(&sdata->local->chanctx_mtx);
+       if (ret < 0)
+               return ret;
+
        return ieee80211_do_open(wdev, true);
 }
 
index 4826c8f5d0b29553e01248d18dce72c75bd12e39..ad5badd783d82f20a17a8b0a74cd85ef8b0dec8e 100644 (file)
@@ -250,6 +250,7 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_sub_if_data *nsdata;
+       int ret;
 
        ASSERT_RTNL();
 
@@ -300,7 +301,10 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
                }
        }
 
-       return 0;
+       mutex_lock(&local->chanctx_mtx);
+       ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
+       mutex_unlock(&local->chanctx_mtx);
+       return ret;
 }
 
 static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
index 436f9887006620890cc7e28e357370c81c3e4cce..5a6cc3382ae943eb11b2762189986fd3e6395981 100644 (file)
@@ -2808,7 +2808,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        enum nl80211_iftype iftype = sdata->wdev.iftype;
        int num[NUM_NL80211_IFTYPES];
        struct ieee80211_chanctx *ctx;
-       int num_different_channels = 1;
+       int num_different_channels = 0;
        int total = 1;
 
        lockdep_assert_held(&local->chanctx_mtx);
@@ -2816,9 +2816,13 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        if (WARN_ON(hweight32(radar_detect) > 1))
                return -EINVAL;
 
-       if (WARN_ON(chanmode == IEEE80211_CHANCTX_SHARED && !chandef->chan))
+       if (WARN_ON(chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
+                   !chandef->chan))
                return -EINVAL;
 
+       if (chandef)
+               num_different_channels = 1;
+
        if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
                return -EINVAL;
 
@@ -2841,7 +2845,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
                        num_different_channels++;
                        continue;
                }
-               if ((chanmode == IEEE80211_CHANCTX_SHARED) &&
+               if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
                    cfg80211_chandef_compatible(chandef,
                                                &ctx->conf.def))
                        continue;
index 5a63c3cbda2e656192c95a7bae2b32b1800cb2b8..33d12e23771cd7237fe966c183bb15a769f545ed 100644 (file)
@@ -439,10 +439,7 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
                for (j = 0; j < c->n_limits; j++) {
                        u16 types = c->limits[j].types;
 
-                       /*
-                        * interface types shouldn't overlap, this is
-                        * used in cfg80211_can_change_interface()
-                        */
+                       /* interface types shouldn't overlap */
                        if (WARN_ON(types & all_iftypes))
                                return -EINVAL;
                        all_iftypes |= types;
@@ -840,7 +837,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
        struct net_device *dev = netdev_notifier_info_to_dev(ptr);
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev;
-       int ret;
 
        if (!wdev)
                return NOTIFY_DONE;
@@ -1003,9 +999,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
        case NETDEV_PRE_UP:
                if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
                        return notifier_from_errno(-EOPNOTSUPP);
-               ret = cfg80211_can_add_interface(rdev, wdev->iftype);
-               if (ret)
-                       return notifier_from_errno(ret);
+               if (rfkill_blocked(rdev->rfkill))
+                       return notifier_from_errno(-ERFKILL);
                break;
        }
 
index 6684c5d965d8755161f4b37f007b6673ad0aca54..5bee6cc94b2151d2a6305f323caa42eac0ffabc3 100644 (file)
@@ -412,28 +412,6 @@ unsigned int
 cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
                              const struct cfg80211_chan_def *chandef);
 
-static inline int
-cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,
-                             struct wireless_dev *wdev,
-                             enum nl80211_iftype iftype)
-{
-       /* TODO: For this function, we'll probably need to keep some
-        * kind of interface combination check in cfg80211...
-        */
-       return cfg80211_can_use_iftype_chan(rdev, wdev, iftype, NULL,
-                                           CHAN_MODE_UNDEFINED, 0);
-}
-
-static inline int
-cfg80211_can_add_interface(struct cfg80211_registered_device *rdev,
-                          enum nl80211_iftype iftype)
-{
-       if (rfkill_blocked(rdev->rfkill))
-               return -ERFKILL;
-
-       return cfg80211_can_change_interface(rdev, NULL, iftype);
-}
-
 static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
 {
        unsigned long end = jiffies;
index 2b99aad33ae0da09fed5f3e400c7787e85364bd5..232d15c0ac6e7d975f89f38616abeefd5924d1fe 100644 (file)
@@ -8969,9 +8969,8 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
        if (wdev->p2p_started)
                return 0;
 
-       err = cfg80211_can_add_interface(rdev, wdev->iftype);
-       if (err)
-               return err;
+       if (rfkill_blocked(rdev->rfkill))
+               return -ERFKILL;
 
        err = rdev_start_p2p_device(rdev, wdev);
        if (err)
index 9bfc4c62150990443c43664e7eb5d8e6c6b1c9bb..5433659a08ee54ae717e08de482efc51b266bfbb 100644 (file)
@@ -888,11 +888,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
                return -EBUSY;
 
        if (ntype != otype && netif_running(dev)) {
-               err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,
-                                                   ntype);
-               if (err)
-                       return err;
-
                dev->ieee80211_ptr->use_4addr = false;
                dev->ieee80211_ptr->mesh_id_up_len = 0;
                wdev_lock(dev->ieee80211_ptr);