All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC 0/3] cfg80211/mac80211: multi-vif csa preparation
@ 2014-02-28 15:06 Michal Kazior
  2014-02-28 15:06 ` [RFC 1/3] cfg80211: allow drivers to iterate over matching combinations Michal Kazior
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Michal Kazior @ 2014-02-28 15:06 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Michal Kazior

Hi,

These are some of the changes I think are
necessary for getting multi-vif and multi-chan
channel switching working.

This is based on Luca's interface combination
patchset v7.

This is taken from my local prototype. However
since Luca's patchsets are still under review
there's nothing more sane I can provide now ;-)

The patch #3 depends on my cfg80211_leave() fix.


Michal Kazior (3):
  cfg80211: allow drivers to iterate over matching combinations
  mac80211: add max channel calculation utility function
  cfg80211: export interface stopping function

 include/net/cfg80211.h     | 41 ++++++++++++++++++++++++++++++++++++++
 net/mac80211/ieee80211_i.h |  1 +
 net/mac80211/util.c        | 43 ++++++++++++++++++++++++++++++++++++++++
 net/wireless/core.c        | 36 +++++++++++++++++++++++++++++++---
 net/wireless/core.h        |  3 +++
 net/wireless/trace.h       | 15 ++++++++++++++
 net/wireless/util.c        | 49 +++++++++++++++++++++++++++++++++++++++-------
 7 files changed, 178 insertions(+), 10 deletions(-)

-- 
1.8.5.3


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC 1/3] cfg80211: allow drivers to iterate over matching combinations
  2014-02-28 15:06 [RFC 0/3] cfg80211/mac80211: multi-vif csa preparation Michal Kazior
@ 2014-02-28 15:06 ` Michal Kazior
  2014-02-28 15:06 ` [RFC 2/3] mac80211: add max channel calculation utility function Michal Kazior
  2014-02-28 15:06 ` [RFC 3/3] cfg80211: export interface stopping function Michal Kazior
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Kazior @ 2014-02-28 15:06 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Michal Kazior

The patch splits cfg80211_check_combinations()
into an iterator function and a simple iteration
user.

This makes it possible for drivers to asses how
many channels can use given iftype setup. This in
turn can be used for future
multi-interface/multi-channel channel switching.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 include/net/cfg80211.h | 27 +++++++++++++++++++++++++++
 net/wireless/util.c    | 44 +++++++++++++++++++++++++++++++++++++-------
 2 files changed, 64 insertions(+), 7 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 23a72e2..f3411c9 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4705,6 +4705,33 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
 				const u8 radar_detect,
 				const int iftype_num[NUM_NL80211_IFTYPES]);
 
+/**
+ * cfg80211_iter_combinations - iterate over matching combinations
+ *
+ * @wiphy: the wiphy
+ * @num_different_channels: the number of different channels we want
+ *	to use for verification
+ * @radar_detect: a bitmap where each bit corresponds to a channel
+ *	width where radar detection is needed, as in the definition of
+ *	&struct ieee80211_iface_combination.@radar_detect_widths
+ * @iftype_num: array with the numbers of interfaces of each interface
+ *	type.  The index is the interface type as specified in &enum
+ *	nl80211_iftype.
+ * @iter: function to call for each matching combination
+ * @data: pointer to pass to iter function
+ *
+ * This function can be called by the driver to check what possible
+ * combinations it fits in at a given moment, e.g. for channel switching
+ * purposes.
+ */
+int cfg80211_iter_combinations(struct wiphy *wiphy,
+			       const int num_different_channels,
+			       const u8 radar_detect,
+			       const int iftype_num[NUM_NL80211_IFTYPES],
+			       void (*iter)(const struct ieee80211_iface_combination *c,
+					    void *data),
+			       void *data);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 378038d30..486b604 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -1248,10 +1248,13 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 	return res;
 }
 
-int cfg80211_check_combinations(struct wiphy *wiphy,
-				const int num_different_channels,
-				const u8 radar_detect,
-				const int iftype_num[NUM_NL80211_IFTYPES])
+int cfg80211_iter_combinations(struct wiphy *wiphy,
+			       const int num_different_channels,
+			       const u8 radar_detect,
+			       const int iftype_num[NUM_NL80211_IFTYPES],
+			       void (*iter)(const struct ieee80211_iface_combination *c,
+					    void *data),
+			       void *data)
 {
 	int i, j, iftype;
 	int num_interfaces = 0;
@@ -1307,13 +1310,40 @@ int cfg80211_check_combinations(struct wiphy *wiphy,
 		/* This combination covered all interface types and
 		 * supported the requested numbers, so we're good.
 		 */
-		kfree(limits);
-		return 0;
+
+		(*iter)(c, data);
  cont:
 		kfree(limits);
 	}
 
-	return -EBUSY;
+	return 0;
+}
+EXPORT_SYMBOL(cfg80211_iter_combinations);
+
+static void
+cfg80211_iter_sum_ifcombs(const struct ieee80211_iface_combination *c,
+			  void *data)
+{
+	int *num = data;
+	(*num)++;
+}
+
+int cfg80211_check_combinations(struct wiphy *wiphy,
+				const int num_different_channels,
+				const u8 radar_detect,
+				const int iftype_num[NUM_NL80211_IFTYPES])
+{
+	int err, num = 0;
+
+	err = cfg80211_iter_combinations(wiphy, num_different_channels,
+					 radar_detect, iftype_num,
+					 cfg80211_iter_sum_ifcombs, &num);
+	if (err)
+		return err;
+	if (num == 0)
+		return -EBUSY;
+
+	return 0;
 }
 EXPORT_SYMBOL(cfg80211_check_combinations);
 
-- 
1.8.5.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [RFC 2/3] mac80211: add max channel calculation utility function
  2014-02-28 15:06 [RFC 0/3] cfg80211/mac80211: multi-vif csa preparation Michal Kazior
  2014-02-28 15:06 ` [RFC 1/3] cfg80211: allow drivers to iterate over matching combinations Michal Kazior
@ 2014-02-28 15:06 ` Michal Kazior
  2014-02-28 15:06 ` [RFC 3/3] cfg80211: export interface stopping function Michal Kazior
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Kazior @ 2014-02-28 15:06 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Michal Kazior

The utility function has no uses yet. It is aimed
at future chanctx reservation management and
channel switching.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 net/mac80211/ieee80211_i.h |  1 +
 net/mac80211/util.c        | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 44 insertions(+)

diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index d3ebe7f..508eecf 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1814,6 +1814,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 				 const struct cfg80211_chan_def *chandef,
 				 enum ieee80211_chanctx_mode chanmode,
 				 u8 radar_detect);
+int ieee80211_max_num_channels(struct ieee80211_local *local);
 
 #ifdef CONFIG_MAC80211_NOINLINE
 #define debug_noinline noinline
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 955b043..7233102 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2877,3 +2877,46 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
 					   num_different_channels,
 					   radar_detect, num);
 }
+
+static void
+ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
+			 void *data)
+{
+	u32 *max_num_different_channels = data;
+
+	*max_num_different_channels = max(*max_num_different_channels,
+					  c->num_different_channels);
+}
+
+int ieee80211_max_num_channels(struct ieee80211_local *local)
+{
+	struct ieee80211_sub_if_data *sdata;
+	int num[NUM_NL80211_IFTYPES] = {};
+	struct ieee80211_chanctx *ctx;
+	int num_different_channels = 0;
+	u8 radar_detect = 0;
+	u32 max_num_different_channels = 1;
+	int err;
+
+	lockdep_assert_held(&local->chanctx_mtx);
+
+	list_for_each_entry(ctx, &local->chanctx_list, list) {
+		num_different_channels++;
+
+		if (ctx->conf.radar_enabled)
+			radar_detect |= BIT(ctx->conf.def.width);
+	}
+
+	list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+		num[sdata->wdev.iftype]++;
+	}
+
+	err = cfg80211_iter_combinations(local->hw.wiphy,
+					 num_different_channels, radar_detect,
+					 num, ieee80211_iter_max_chans,
+					 &max_num_different_channels);
+	if (err < 0)
+		return err;
+
+	return max_num_different_channels;
+}
-- 
1.8.5.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [RFC 3/3] cfg80211: export interface stopping function
  2014-02-28 15:06 [RFC 0/3] cfg80211/mac80211: multi-vif csa preparation Michal Kazior
  2014-02-28 15:06 ` [RFC 1/3] cfg80211: allow drivers to iterate over matching combinations Michal Kazior
  2014-02-28 15:06 ` [RFC 2/3] mac80211: add max channel calculation utility function Michal Kazior
@ 2014-02-28 15:06 ` Michal Kazior
  2 siblings, 0 replies; 4+ messages in thread
From: Michal Kazior @ 2014-02-28 15:06 UTC (permalink / raw)
  To: linux-wireless; +Cc: johannes, Michal Kazior

This exports a new cfg80211_stop_iface() function.

This is intended for driver internal interface
combination management and channel switching. This
is probably most useful for AP or provide a
unified way to stopping interface operation from a
driver.

Due to locking issues (it re-enters driver) the
call is asynchronous and uses cfg80211 even
list/worker.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
---
 include/net/cfg80211.h | 14 ++++++++++++++
 net/wireless/core.c    | 36 +++++++++++++++++++++++++++++++++---
 net/wireless/core.h    |  3 +++
 net/wireless/trace.h   | 15 +++++++++++++++
 net/wireless/util.c    |  5 +++++
 5 files changed, 70 insertions(+), 3 deletions(-)

diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index f3411c9..15376c0 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4732,6 +4732,20 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
 					    void *data),
 			       void *data);
 
+/**
+ * cfg80211_stop_iface - stop operation on given interface
+ *
+ * @wiphy: the wiphy
+ * @wdev: wireless device
+ *
+ * Cease operation of the given interface as if the interface was brought down.
+ * This stops beaconing or disconnects for a BSS.
+ *
+ * This doesn't need any locks and is asynchronous. This is intended for
+ * channel switching and internal driver interface combination management.
+ */
+void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/net/wireless/core.c b/net/wireless/core.c
index afd0f08..b2f064f 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -748,14 +748,14 @@ void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
 		rdev->num_running_monitor_ifaces += num;
 }
 
-void cfg80211_leave(struct cfg80211_registered_device *rdev,
-		    struct wireless_dev *wdev)
+void __cfg80211_leave(struct cfg80211_registered_device *rdev,
+		      struct wireless_dev *wdev)
 {
 	struct net_device *dev = wdev->netdev;
 
 	ASSERT_RTNL();
+	ASSERT_WDEV_LOCK(wdev);
 
-	wdev_lock(wdev);
 	switch (wdev->iftype) {
 	case NL80211_IFTYPE_ADHOC:
 		__cfg80211_leave_ibss(rdev, dev, true);
@@ -786,9 +786,39 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev,
 	}
 
 	wdev->beacon_interval = 0;
+}
+
+void cfg80211_leave(struct cfg80211_registered_device *rdev,
+		    struct wireless_dev *wdev)
+{
+	ASSERT_RTNL();
+
+	wdev_lock(wdev);
+	__cfg80211_leave(rdev, wdev);
 	wdev_unlock(wdev);
 }
 
+void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
+{
+	struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
+	struct cfg80211_event *ev;
+	unsigned long flags;
+
+	trace_cfg80211_stop_iface(wiphy, wdev);
+
+	ev = kzalloc(sizeof(*ev), GFP_ATOMIC);
+	if (!ev)
+		return;
+
+	ev->type = EVENT_STOPPED;
+
+	spin_lock_irqsave(&wdev->event_lock, flags);
+	list_add_tail(&ev->list, &wdev->event_list);
+	spin_unlock_irqrestore(&wdev->event_lock, flags);
+	queue_work(cfg80211_wq, &rdev->event_work);
+}
+EXPORT_SYMBOL(cfg80211_stop_iface);
+
 static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
 					 unsigned long state, void *ptr)
 {
diff --git a/net/wireless/core.h b/net/wireless/core.h
index 78e6847..402a653 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -182,6 +182,7 @@ enum cfg80211_event_type {
 	EVENT_ROAMED,
 	EVENT_DISCONNECTED,
 	EVENT_IBSS_JOINED,
+	EVENT_STOPPED,
 };
 
 struct cfg80211_event {
@@ -439,6 +440,8 @@ int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
 void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
 			       enum nl80211_iftype iftype, int num);
 
+void __cfg80211_leave(struct cfg80211_registered_device *rdev,
+		      struct wireless_dev *wdev);
 void cfg80211_leave(struct cfg80211_registered_device *rdev,
 		    struct wireless_dev *wdev);
 
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index aabccf1..24acf96 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2615,6 +2615,21 @@ TRACE_EVENT(cfg80211_ft_event,
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(target_ap))
 );
 
+TRACE_EVENT(cfg80211_stop_iface,
+	TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
+	TP_ARGS(wiphy, wdev),
+	TP_STRUCT__entry(
+		WIPHY_ENTRY
+		WDEV_ENTRY
+	),
+	TP_fast_assign(
+		WIPHY_ASSIGN;
+		WDEV_ASSIGN;
+	),
+	TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT,
+		  WIPHY_PR_ARG, WDEV_PR_ARG)
+);
+
 #endif /* !__RDEV_OPS_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 486b604..2236c08 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -789,6 +789,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
 	unsigned long flags;
 	const u8 *bssid = NULL;
 
+	ASSERT_RTNL();
+
 	spin_lock_irqsave(&wdev->event_lock, flags);
 	while (!list_empty(&wdev->event_list)) {
 		ev = list_first_entry(&wdev->event_list,
@@ -823,6 +825,9 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev)
 			__cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid,
 					       ev->ij.channel);
 			break;
+		case EVENT_STOPPED:
+			__cfg80211_leave(wiphy_to_dev(wdev->wiphy), wdev);
+			break;
 		}
 		wdev_unlock(wdev);
 
-- 
1.8.5.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2014-02-28 15:12 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-02-28 15:06 [RFC 0/3] cfg80211/mac80211: multi-vif csa preparation Michal Kazior
2014-02-28 15:06 ` [RFC 1/3] cfg80211: allow drivers to iterate over matching combinations Michal Kazior
2014-02-28 15:06 ` [RFC 2/3] mac80211: add max channel calculation utility function Michal Kazior
2014-02-28 15:06 ` [RFC 3/3] cfg80211: export interface stopping function Michal Kazior

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.