diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2009-12-23 07:15:32 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-12-28 16:54:51 -0500 |
commit | a80f7c0b088187c8471b441d461e937991870661 (patch) | |
tree | f673c08009a03f2e988a638510b112a5584bea11 | |
parent | 9607e6b66a0d25ca63b70d54a4283fa13d8f7c9d (diff) |
mac80211: introduce flush operation
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@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 11 | ||||
-rw-r--r-- | include/net/mac80211.h | 5 | ||||
-rw-r--r-- | net/mac80211/driver-ops.h | 7 | ||||
-rw-r--r-- | net/mac80211/driver-trace.h | 21 | ||||
-rw-r--r-- | net/mac80211/iface.c | 2 | ||||
-rw-r--r-- | net/mac80211/scan.c | 13 |
6 files changed, 57 insertions, 2 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 718a5f198c30..4dee69a38c1d 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -896,6 +896,16 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw, | |||
896 | return 0; | 896 | return 0; |
897 | } | 897 | } |
898 | 898 | ||
899 | static void mac80211_hwsim_flush(struct ieee80211_hw *hw, bool drop) | ||
900 | { | ||
901 | /* | ||
902 | * In this special case, there's nothing we need to | ||
903 | * do because hwsim does transmission synchronously. | ||
904 | * In the future, when it does transmissions via | ||
905 | * userspace, we may need to do something. | ||
906 | */ | ||
907 | } | ||
908 | |||
899 | 909 | ||
900 | static const struct ieee80211_ops mac80211_hwsim_ops = | 910 | static const struct ieee80211_ops mac80211_hwsim_ops = |
901 | { | 911 | { |
@@ -912,6 +922,7 @@ static const struct ieee80211_ops mac80211_hwsim_ops = | |||
912 | .conf_tx = mac80211_hwsim_conf_tx, | 922 | .conf_tx = mac80211_hwsim_conf_tx, |
913 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 923 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
914 | .ampdu_action = mac80211_hwsim_ampdu_action, | 924 | .ampdu_action = mac80211_hwsim_ampdu_action, |
925 | .flush = mac80211_hwsim_flush, | ||
915 | }; | 926 | }; |
916 | 927 | ||
917 | 928 | ||
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 494ac69ff477..77ea34b03285 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1545,6 +1545,10 @@ enum ieee80211_ampdu_mlme_action { | |||
1545 | * and need to call wiphy_rfkill_set_hw_state() in the callback. | 1545 | * and need to call wiphy_rfkill_set_hw_state() in the callback. |
1546 | * | 1546 | * |
1547 | * @testmode_cmd: Implement a cfg80211 test mode command. | 1547 | * @testmode_cmd: Implement a cfg80211 test mode command. |
1548 | * | ||
1549 | * @flush: Flush all pending frames from the hardware queue, making sure | ||
1550 | * that the hardware queues are empty. If the parameter @drop is set | ||
1551 | * to %true, pending frames may be dropped. | ||
1548 | */ | 1552 | */ |
1549 | struct ieee80211_ops { | 1553 | struct ieee80211_ops { |
1550 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); | 1554 | int (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); |
@@ -1601,6 +1605,7 @@ struct ieee80211_ops { | |||
1601 | #ifdef CONFIG_NL80211_TESTMODE | 1605 | #ifdef CONFIG_NL80211_TESTMODE |
1602 | int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); | 1606 | int (*testmode_cmd)(struct ieee80211_hw *hw, void *data, int len); |
1603 | #endif | 1607 | #endif |
1608 | void (*flush)(struct ieee80211_hw *hw, bool drop); | ||
1604 | }; | 1609 | }; |
1605 | 1610 | ||
1606 | /** | 1611 | /** |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index 727e4cf7b8a6..cbe133bcdf34 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -259,4 +259,11 @@ static inline void drv_rfkill_poll(struct ieee80211_local *local) | |||
259 | if (local->ops->rfkill_poll) | 259 | if (local->ops->rfkill_poll) |
260 | local->ops->rfkill_poll(&local->hw); | 260 | local->ops->rfkill_poll(&local->hw); |
261 | } | 261 | } |
262 | |||
263 | static inline void drv_flush(struct ieee80211_local *local, bool drop) | ||
264 | { | ||
265 | trace_drv_flush(local, drop); | ||
266 | if (local->ops->flush) | ||
267 | local->ops->flush(&local->hw, drop); | ||
268 | } | ||
262 | #endif /* __MAC80211_DRIVER_OPS */ | 269 | #endif /* __MAC80211_DRIVER_OPS */ |
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h index 7a849b920165..977cc7528bc6 100644 --- a/net/mac80211/driver-trace.h +++ b/net/mac80211/driver-trace.h | |||
@@ -690,6 +690,27 @@ TRACE_EVENT(drv_ampdu_action, | |||
690 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret | 690 | LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->action, __entry->tid, __entry->ret |
691 | ) | 691 | ) |
692 | ); | 692 | ); |
693 | |||
694 | TRACE_EVENT(drv_flush, | ||
695 | TP_PROTO(struct ieee80211_local *local, bool drop), | ||
696 | |||
697 | TP_ARGS(local, drop), | ||
698 | |||
699 | TP_STRUCT__entry( | ||
700 | LOCAL_ENTRY | ||
701 | __field(bool, drop) | ||
702 | ), | ||
703 | |||
704 | TP_fast_assign( | ||
705 | LOCAL_ASSIGN; | ||
706 | __entry->drop = drop; | ||
707 | ), | ||
708 | |||
709 | TP_printk( | ||
710 | LOCAL_PR_FMT " drop:%d", | ||
711 | LOCAL_PR_ARG, __entry->drop | ||
712 | ) | ||
713 | ); | ||
693 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ | 714 | #endif /* !__MAC80211_DRIVER_TRACE || TRACE_HEADER_MULTI_READ */ |
694 | 715 | ||
695 | #undef TRACE_INCLUDE_PATH | 716 | #undef TRACE_INCLUDE_PATH |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 1ceca14331d4..389dc8d880f3 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -917,6 +917,8 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
917 | wiphy_name(local->hw.wiphy)); | 917 | wiphy_name(local->hw.wiphy)); |
918 | #endif | 918 | #endif |
919 | 919 | ||
920 | drv_flush(local, false); | ||
921 | |||
920 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; | 922 | local->hw.conf.flags |= IEEE80211_CONF_IDLE; |
921 | return IEEE80211_CONF_CHANGE_IDLE; | 923 | return IEEE80211_CONF_CHANGE_IDLE; |
922 | } | 924 | } |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index ae1830056521..d98c45e5528b 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -418,9 +418,10 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
418 | local->next_scan_state = SCAN_DECISION; | 418 | local->next_scan_state = SCAN_DECISION; |
419 | local->scan_channel_idx = 0; | 419 | local->scan_channel_idx = 0; |
420 | 420 | ||
421 | drv_flush(local, false); | ||
422 | |||
421 | ieee80211_configure_filter(local); | 423 | ieee80211_configure_filter(local); |
422 | 424 | ||
423 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | ||
424 | ieee80211_queue_delayed_work(&local->hw, | 425 | ieee80211_queue_delayed_work(&local->hw, |
425 | &local->scan_work, | 426 | &local->scan_work, |
426 | IEEE80211_CHANNEL_TIME); | 427 | IEEE80211_CHANNEL_TIME); |
@@ -584,8 +585,16 @@ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *loca | |||
584 | 585 | ||
585 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | 586 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); |
586 | 587 | ||
588 | /* | ||
589 | * What if the nullfunc frames didn't arrive? | ||
590 | */ | ||
591 | drv_flush(local, false); | ||
592 | if (local->ops->flush) | ||
593 | *next_delay = 0; | ||
594 | else | ||
595 | *next_delay = HZ / 10; | ||
596 | |||
587 | /* advance to the next channel to be scanned */ | 597 | /* advance to the next channel to be scanned */ |
588 | *next_delay = HZ / 10; | ||
589 | local->next_scan_state = SCAN_SET_CHANNEL; | 598 | local->next_scan_state = SCAN_SET_CHANNEL; |
590 | } | 599 | } |
591 | 600 | ||