forked from mirrors/linux
		
	cfg80211/mac80211: move more combination checks to mac80211
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>
This commit is contained in:
		
							parent
							
								
									71965c1d04
								
							
						
					
					
						commit
						b6a550156b
					
				
					 7 changed files with 26 additions and 42 deletions
				
			
		| 
						 | 
					@ -109,6 +109,15 @@ static int ieee80211_change_iface(struct wiphy *wiphy,
 | 
				
			||||||
static int ieee80211_start_p2p_device(struct wiphy *wiphy,
 | 
					static int ieee80211_start_p2p_device(struct wiphy *wiphy,
 | 
				
			||||||
				      struct wireless_dev *wdev)
 | 
									      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);
 | 
						return ieee80211_do_open(wdev, true);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -250,6 +250,7 @@ static int ieee80211_check_concurrent_iface(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ieee80211_local *local = sdata->local;
 | 
						struct ieee80211_local *local = sdata->local;
 | 
				
			||||||
	struct ieee80211_sub_if_data *nsdata;
 | 
						struct ieee80211_sub_if_data *nsdata;
 | 
				
			||||||
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ASSERT_RTNL();
 | 
						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,
 | 
					static int ieee80211_check_queues(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2808,7 +2808,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	enum nl80211_iftype iftype = sdata->wdev.iftype;
 | 
						enum nl80211_iftype iftype = sdata->wdev.iftype;
 | 
				
			||||||
	int num[NUM_NL80211_IFTYPES];
 | 
						int num[NUM_NL80211_IFTYPES];
 | 
				
			||||||
	struct ieee80211_chanctx *ctx;
 | 
						struct ieee80211_chanctx *ctx;
 | 
				
			||||||
	int num_different_channels = 1;
 | 
						int num_different_channels = 0;
 | 
				
			||||||
	int total = 1;
 | 
						int total = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lockdep_assert_held(&local->chanctx_mtx);
 | 
						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))
 | 
						if (WARN_ON(hweight32(radar_detect) > 1))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (WARN_ON(chanmode == IEEE80211_CHANCTX_SHARED && !chandef->chan))
 | 
						if (WARN_ON(chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
 | 
				
			||||||
 | 
							    !chandef->chan))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (chandef)
 | 
				
			||||||
 | 
							num_different_channels = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
 | 
						if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2841,7 +2845,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			num_different_channels++;
 | 
								num_different_channels++;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if ((chanmode == IEEE80211_CHANCTX_SHARED) &&
 | 
							if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
 | 
				
			||||||
		    cfg80211_chandef_compatible(chandef,
 | 
							    cfg80211_chandef_compatible(chandef,
 | 
				
			||||||
						&ctx->conf.def))
 | 
											&ctx->conf.def))
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -439,10 +439,7 @@ static int wiphy_verify_combinations(struct wiphy *wiphy)
 | 
				
			||||||
		for (j = 0; j < c->n_limits; j++) {
 | 
							for (j = 0; j < c->n_limits; j++) {
 | 
				
			||||||
			u16 types = c->limits[j].types;
 | 
								u16 types = c->limits[j].types;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			/*
 | 
								/* interface types shouldn't overlap */
 | 
				
			||||||
			 * interface types shouldn't overlap, this is
 | 
					 | 
				
			||||||
			 * used in cfg80211_can_change_interface()
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (WARN_ON(types & all_iftypes))
 | 
								if (WARN_ON(types & all_iftypes))
 | 
				
			||||||
				return -EINVAL;
 | 
									return -EINVAL;
 | 
				
			||||||
			all_iftypes |= types;
 | 
								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 net_device *dev = netdev_notifier_info_to_dev(ptr);
 | 
				
			||||||
	struct wireless_dev *wdev = dev->ieee80211_ptr;
 | 
						struct wireless_dev *wdev = dev->ieee80211_ptr;
 | 
				
			||||||
	struct cfg80211_registered_device *rdev;
 | 
						struct cfg80211_registered_device *rdev;
 | 
				
			||||||
	int ret;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!wdev)
 | 
						if (!wdev)
 | 
				
			||||||
		return NOTIFY_DONE;
 | 
							return NOTIFY_DONE;
 | 
				
			||||||
| 
						 | 
					@ -1003,9 +999,8 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 | 
				
			||||||
	case NETDEV_PRE_UP:
 | 
						case NETDEV_PRE_UP:
 | 
				
			||||||
		if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
 | 
							if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype)))
 | 
				
			||||||
			return notifier_from_errno(-EOPNOTSUPP);
 | 
								return notifier_from_errno(-EOPNOTSUPP);
 | 
				
			||||||
		ret = cfg80211_can_add_interface(rdev, wdev->iftype);
 | 
							if (rfkill_blocked(rdev->rfkill))
 | 
				
			||||||
		if (ret)
 | 
								return notifier_from_errno(-ERFKILL);
 | 
				
			||||||
			return notifier_from_errno(ret);
 | 
					 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -412,28 +412,6 @@ unsigned int
 | 
				
			||||||
cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
 | 
					cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy,
 | 
				
			||||||
			      const struct cfg80211_chan_def *chandef);
 | 
								      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)
 | 
					static inline unsigned int elapsed_jiffies_msecs(unsigned long start)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned long end = jiffies;
 | 
						unsigned long end = jiffies;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8969,9 +8969,8 @@ static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info)
 | 
				
			||||||
	if (wdev->p2p_started)
 | 
						if (wdev->p2p_started)
 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = cfg80211_can_add_interface(rdev, wdev->iftype);
 | 
						if (rfkill_blocked(rdev->rfkill))
 | 
				
			||||||
	if (err)
 | 
							return -ERFKILL;
 | 
				
			||||||
		return err;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = rdev_start_p2p_device(rdev, wdev);
 | 
						err = rdev_start_p2p_device(rdev, wdev);
 | 
				
			||||||
	if (err)
 | 
						if (err)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -888,11 +888,6 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,
 | 
				
			||||||
		return -EBUSY;
 | 
							return -EBUSY;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (ntype != otype && netif_running(dev)) {
 | 
						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->use_4addr = false;
 | 
				
			||||||
		dev->ieee80211_ptr->mesh_id_up_len = 0;
 | 
							dev->ieee80211_ptr->mesh_id_up_len = 0;
 | 
				
			||||||
		wdev_lock(dev->ieee80211_ptr);
 | 
							wdev_lock(dev->ieee80211_ptr);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue