Search Linux Wireless

[PATCH] mac80211: introduce flush operation

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



We've long lacked a good confirmation that frames
have really gone out, e.g. before going off-channel
for a scan. Add a flush() operation that drivers
can implement to provide that confirmation, and use
it in a few places:
 * before scanning sends the nullfunc frames
 * after scanning sends the nullfunc frames, if any
 * when going idle, to send any pending frames

Signed-off-by: Johannes Berg <johannes@xxxxxxxxxxxxxxxx>
---
 drivers/net/wireless/mac80211_hwsim.c |   11 +++++++++++
 include/net/mac80211.h                |    5 +++++
 net/mac80211/driver-ops.h             |    7 +++++++
 net/mac80211/driver-trace.h           |   21 +++++++++++++++++++++
 net/mac80211/iface.c                  |    2 ++
 net/mac80211/scan.c                   |   13 +++++++++++--
 6 files changed, 57 insertions(+), 2 deletions(-)

--- wireless-testing.orig/include/net/mac80211.h	2009-11-29 11:33:29.000000000 +0100
+++ wireless-testing/include/net/mac80211.h	2009-11-29 11:33:52.000000000 +0100
@@ -1486,6 +1486,10 @@ enum ieee80211_ampdu_mlme_action {
  *	and need to call wiphy_rfkill_set_hw_state() in the callback.
  *
  * @testmode_cmd: Implement a cfg80211 test mode command.
+ *
+ * @flush: Flush all pending frames from the hardware queue, making sure
+ *	that the hardware queues are empty. If the parameter @drop is set
+ *	to %true, pending frames may be dropped.
  */
 struct ieee80211_ops {
 	int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1542,6 +1546,7 @@ struct ieee80211_ops {
 #ifdef CONFIG_NL80211_TESTMODE
 	int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len);
 #endif
+	void (*flush)(struct ieee80211_hw *hw, bool drop);
 };
 
 /**
--- wireless-testing.orig/net/mac80211/driver-ops.h	2009-11-29 11:33:01.000000000 +0100
+++ wireless-testing/net/mac80211/driver-ops.h	2009-11-29 11:33:52.000000000 +0100
@@ -259,4 +259,11 @@ static inline void drv_rfkill_poll(struc
 	if (local->ops->rfkill_poll)
 		local->ops->rfkill_poll(&local->hw);
 }
+
+static inline void drv_flush(struct ieee80211_local *local, bool drop)
+{
+	trace_drv_flush(local, drop);
+	if (local->ops->flush)
+		local->ops->flush(&local->hw, drop);
+}
 #endif /* __MAC80211_DRIVER_OPS */
--- wireless-testing.orig/net/mac80211/driver-trace.h	2009-11-29 11:33:01.000000000 +0100
+++ wireless-testing/net/mac80211/driver-trace.h	2009-11-29 11:33:52.000000000 +0100
@@ -688,6 +688,27 @@ TRACE_EVENT(drv_ampdu_action,
 		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret
 	)
 );
+
+TRACE_EVENT(drv_flush,
+	TP_PROTO(struct ieee80211_local *local, bool drop),
+
+	TP_ARGS(local, drop),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		__field(bool, drop)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		__entry->drop = drop;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT " drop:%d",
+		LOCAL_PR_ARG, __entry->drop
+	)
+);
 #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */
 
 #undef TRACE_INCLUDE_PATH
--- wireless-testing.orig/net/mac80211/scan.c	2009-11-29 11:33:01.000000000 +0100
+++ wireless-testing/net/mac80211/scan.c	2009-11-29 11:33:52.000000000 +0100
@@ -406,9 +406,10 @@ static int ieee80211_start_sw_scan(struc
 	local->next_scan_state = SCAN_DECISION;
 	local->scan_channel_idx = 0;
 
+	drv_flush(local, false);
+
 	ieee80211_configure_filter(local);
 
-	/* TODO: start scan as soon as all nullfunc frames are ACKed */
 	ieee80211_queue_delayed_work(&local->hw,
 				     &local->scan_work,
 				     IEEE80211_CHANNEL_TIME);
@@ -572,8 +573,16 @@ static void ieee80211_scan_state_leave_o
 
 	__set_bit(SCAN_OFF_CHANNEL, &local->scanning);
 
+	/*
+	 * What if the nullfunc frames didn't arrive?
+	 */
+	drv_flush(local, false);
+	if (local->ops->flush)
+		*next_delay = 0;
+	else
+		*next_delay = HZ / 10;
+
 	/* advance to the next channel to be scanned */
-	*next_delay = HZ / 10;
 	local->next_scan_state = SCAN_SET_CHANNEL;
 }
 
--- wireless-testing.orig/net/mac80211/iface.c	2009-11-29 11:33:01.000000000 +0100
+++ wireless-testing/net/mac80211/iface.c	2009-11-29 11:33:52.000000000 +0100
@@ -926,6 +926,8 @@ static u32 ieee80211_idle_on(struct ieee
 	       wiphy_name(local->hw.wiphy));
 #endif
 
+	drv_flush(local, false);
+
 	local->hw.conf.flags |= IEEE80211_CONF_IDLE;
 	return IEEE80211_CONF_CHANGE_IDLE;
 }
--- wireless-testing.orig/drivers/net/wireless/mac80211_hwsim.c	2009-11-29 11:33:01.000000000 +0100
+++ wireless-testing/drivers/net/wireless/mac80211_hwsim.c	2009-11-29 11:33:52.000000000 +0100
@@ -852,6 +852,16 @@ static int mac80211_hwsim_ampdu_action(s
 	return 0;
 }
 
+static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop)
+{
+	/*
+	 * In this special case, there's nothing we need to
+	 * do because hwsim does transmission synchronously.
+	 * In the future, when it does transmissions via
+	 * userspace, we may need to do something.
+	 */
+}
+
 
 static const struct ieee80211_ops mac80211_hwsim_ops =
 {
@@ -868,6 +878,7 @@ static const struct ieee80211_ops mac802
 	.conf_tx = mac80211_hwsim_conf_tx,
 	CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
 	.ampdu_action = mac80211_hwsim_ampdu_action,
+	.flush = mac80211_hwsim_flush,
 };
 
 


--
To unsubscribe from this list: send the line "unsubscribe linux-wireless" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Bluetooth]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Samba]     [Device Mapper]
  Powered by Linux