2009-12-23 13:15:40 +01:00
/*
* Off - channel operation helpers
*
* Copyright 2003 , Jouni Malinen < jkmaline @ cc . hut . fi >
* Copyright 2004 , Instant802 Networks , Inc .
* Copyright 2005 , Devicescape Software , Inc .
* Copyright 2006 - 2007 Jiri Benc < jbenc @ suse . cz >
* Copyright 2007 , Michael Wu < flamingice @ sourmilk . net >
* Copyright 2009 Johannes Berg < johannes @ sipsolutions . net >
*
* This program is free software ; you can redistribute it and / or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation .
*/
2011-07-15 11:47:34 -04:00
# include <linux/export.h>
2009-12-23 13:15:40 +01:00
# include <net/mac80211.h>
# include "ieee80211_i.h"
2010-12-18 17:20:47 +01:00
# include "driver-trace.h"
2009-12-23 13:15:40 +01:00
/*
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
* Tell our hardware to disable PS .
* Optionally inform AP that we will go to sleep so that it will buffer
* the frames while we are doing off - channel work . This is optional
* because we * may * be doing work on - operating channel , and want our
* hardware unconditionally awake , but still let the AP send us normal frames .
2009-12-23 13:15:40 +01:00
*/
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
static void ieee80211_offchannel_ps_enable ( struct ieee80211_sub_if_data * sdata ,
bool tell_ap )
2009-12-23 13:15:40 +01:00
{
struct ieee80211_local * local = sdata - > local ;
2010-09-16 15:12:31 -04:00
struct ieee80211_if_managed * ifmgd = & sdata - > u . mgd ;
2009-12-23 13:15:40 +01:00
local - > offchannel_ps_enabled = false ;
/* FIXME: what to do when local->pspolling is true? */
del_timer_sync ( & local - > dynamic_ps_timer ) ;
2010-09-16 15:12:33 -04:00
del_timer_sync ( & ifmgd - > bcn_mon_timer ) ;
2010-09-16 15:12:31 -04:00
del_timer_sync ( & ifmgd - > conn_mon_timer ) ;
2009-12-23 13:15:40 +01:00
cancel_work_sync ( & local - > dynamic_ps_enable_work ) ;
if ( local - > hw . conf . flags & IEEE80211_CONF_PS ) {
local - > offchannel_ps_enabled = true ;
local - > hw . conf . flags & = ~ IEEE80211_CONF_PS ;
ieee80211_hw_config ( local , IEEE80211_CONF_CHANGE_PS ) ;
}
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
if ( tell_ap & & ( ! local - > offchannel_ps_enabled | |
! ( local - > hw . flags & IEEE80211_HW_PS_NULLFUNC_STACK ) ) )
2009-12-23 13:15:40 +01:00
/*
* If power save was enabled , no need to send a nullfunc
* frame because AP knows that we are sleeping . But if the
* hardware is creating the nullfunc frame for power save
* status ( ie . IEEE80211_HW_PS_NULLFUNC_STACK is not
* enabled ) and power save was enabled , the firmware just
* sent a null frame with power save disabled . So we need
* to send a new nullfunc frame to inform the AP that we
* are again sleeping .
*/
ieee80211_send_nullfunc ( local , sdata , 1 ) ;
}
/* inform AP that we are awake again, unless power save is enabled */
static void ieee80211_offchannel_ps_disable ( struct ieee80211_sub_if_data * sdata )
{
struct ieee80211_local * local = sdata - > local ;
if ( ! local - > ps_sdata )
ieee80211_send_nullfunc ( local , sdata , 0 ) ;
else if ( local - > offchannel_ps_enabled ) {
/*
* In ! IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
* will send a nullfunc frame with the powersave bit set
* even though the AP already knows that we are sleeping .
* This could be avoided by sending a null frame with power
* save bit disabled before enabling the power save , but
* this doesn ' t gain anything .
*
* When IEEE80211_HW_PS_NULLFUNC_STACK is enabled , no need
* to send a nullfunc frame because AP already knows that
* we are sleeping , let ' s just enable power save mode in
* hardware .
*/
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
/* TODO: Only set hardware if CONF_PS changed?
* TODO : Should we set offchannel_ps_enabled to false ?
*/
2009-12-23 13:15:40 +01:00
local - > hw . conf . flags | = IEEE80211_CONF_PS ;
ieee80211_hw_config ( local , IEEE80211_CONF_CHANGE_PS ) ;
} else if ( local - > hw . conf . dynamic_ps_timeout > 0 ) {
/*
* If IEEE80211_CONF_PS was not set and the dynamic_ps_timer
* had been running before leaving the operating channel ,
* restart the timer now and send a nullfunc frame to inform
* the AP that we are awake .
*/
ieee80211_send_nullfunc ( local , sdata , 0 ) ;
mod_timer ( & local - > dynamic_ps_timer , jiffies +
msecs_to_jiffies ( local - > hw . conf . dynamic_ps_timeout ) ) ;
}
2010-09-16 15:12:31 -04:00
2010-09-16 15:12:33 -04:00
ieee80211_sta_reset_beacon_monitor ( sdata ) ;
2010-09-16 15:12:31 -04:00
ieee80211_sta_reset_conn_monitor ( sdata ) ;
2009-12-23 13:15:40 +01:00
}
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
void ieee80211_offchannel_stop_vifs ( struct ieee80211_local * local ,
bool offchannel_ps_enable )
2009-12-23 13:15:40 +01:00
{
struct ieee80211_sub_if_data * sdata ;
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
/*
* notify the AP about us leaving the channel and stop all
* STA interfaces .
*/
2009-12-23 13:15:40 +01:00
mutex_lock ( & local - > iflist_mtx ) ;
list_for_each_entry ( sdata , & local - > interfaces , list ) {
if ( ! ieee80211_sdata_running ( sdata ) )
continue ;
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
if ( sdata - > vif . type ! = NL80211_IFTYPE_MONITOR )
set_bit ( SDATA_STATE_OFFCHANNEL , & sdata - > state ) ;
/* Check to see if we should disable beaconing. */
2009-12-23 13:15:40 +01:00
if ( sdata - > vif . type = = NL80211_IFTYPE_AP | |
sdata - > vif . type = = NL80211_IFTYPE_ADHOC | |
sdata - > vif . type = = NL80211_IFTYPE_MESH_POINT )
ieee80211_bss_info_change_notify (
sdata , BSS_CHANGED_BEACON_ENABLED ) ;
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
if ( sdata - > vif . type ! = NL80211_IFTYPE_MONITOR ) {
2010-01-06 17:22:54 -05:00
netif_tx_stop_all_queues ( sdata - > dev ) ;
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
if ( offchannel_ps_enable & &
( sdata - > vif . type = = NL80211_IFTYPE_STATION ) & &
sdata - > u . mgd . associated )
ieee80211_offchannel_ps_enable ( sdata , true ) ;
2010-08-27 13:45:28 +02:00
}
2009-12-23 13:15:40 +01:00
}
mutex_unlock ( & local - > iflist_mtx ) ;
}
void ieee80211_offchannel_return ( struct ieee80211_local * local ,
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
bool offchannel_ps_disable )
2009-12-23 13:15:40 +01:00
{
struct ieee80211_sub_if_data * sdata ;
mutex_lock ( & local - > iflist_mtx ) ;
list_for_each_entry ( sdata , & local - > interfaces , list ) {
2011-12-23 01:48:06 +02:00
if ( sdata - > vif . type ! = NL80211_IFTYPE_MONITOR )
clear_bit ( SDATA_STATE_OFFCHANNEL , & sdata - > state ) ;
2009-12-23 13:15:40 +01:00
if ( ! ieee80211_sdata_running ( sdata ) )
continue ;
/* Tell AP we're back */
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2011-02-04 11:54:17 -08:00
if ( offchannel_ps_disable & &
sdata - > vif . type = = NL80211_IFTYPE_STATION ) {
2009-12-23 13:15:40 +01:00
if ( sdata - > u . mgd . associated )
ieee80211_offchannel_ps_disable ( sdata ) ;
}
2010-08-27 13:45:28 +02:00
if ( sdata - > vif . type ! = NL80211_IFTYPE_MONITOR ) {
/*
* This may wake up queues even though the driver
* currently has them stopped . This is not very
* likely , since the driver won ' t have gotten any
* ( or hardly any ) new packets while we weren ' t
* on the right channel , and even if it happens
* it will at most lead to queueing up one more
* packet per queue in mac80211 rather than on
* the interface qdisc .
*/
2010-01-14 23:20:31 +01:00
netif_tx_wake_all_queues ( sdata - > dev ) ;
2010-08-27 13:45:28 +02:00
}
2010-01-14 23:20:31 +01:00
2011-11-29 10:20:02 +01:00
if ( sdata - > vif . type = = NL80211_IFTYPE_AP | |
sdata - > vif . type = = NL80211_IFTYPE_ADHOC | |
sdata - > vif . type = = NL80211_IFTYPE_MESH_POINT )
2009-12-23 13:15:40 +01:00
ieee80211_bss_info_change_notify (
sdata , BSS_CHANGED_BEACON_ENABLED ) ;
}
mutex_unlock ( & local - > iflist_mtx ) ;
}
2010-12-18 17:20:47 +01:00
static void ieee80211_hw_roc_start ( struct work_struct * work )
{
struct ieee80211_local * local =
container_of ( work , struct ieee80211_local , hw_roc_start ) ;
2010-12-18 17:20:48 +01:00
struct ieee80211_sub_if_data * sdata ;
2010-12-18 17:20:47 +01:00
mutex_lock ( & local - > mtx ) ;
if ( ! local - > hw_roc_channel ) {
mutex_unlock ( & local - > mtx ) ;
return ;
}
2010-12-18 17:20:48 +01:00
if ( local - > hw_roc_skb ) {
sdata = IEEE80211_DEV_TO_SUB_IF ( local - > hw_roc_dev ) ;
ieee80211_tx_skb ( sdata , local - > hw_roc_skb ) ;
local - > hw_roc_skb = NULL ;
} else {
cfg80211_ready_on_channel ( local - > hw_roc_dev ,
local - > hw_roc_cookie ,
local - > hw_roc_channel ,
local - > hw_roc_channel_type ,
local - > hw_roc_duration ,
GFP_KERNEL ) ;
}
2011-11-16 13:34:55 +01:00
ieee80211_recalc_idle ( local ) ;
2010-12-18 17:20:47 +01:00
mutex_unlock ( & local - > mtx ) ;
}
void ieee80211_ready_on_channel ( struct ieee80211_hw * hw )
{
struct ieee80211_local * local = hw_to_local ( hw ) ;
trace_api_ready_on_channel ( local ) ;
ieee80211_queue_work ( hw , & local - > hw_roc_start ) ;
}
EXPORT_SYMBOL_GPL ( ieee80211_ready_on_channel ) ;
static void ieee80211_hw_roc_done ( struct work_struct * work )
{
struct ieee80211_local * local =
container_of ( work , struct ieee80211_local , hw_roc_done ) ;
mutex_lock ( & local - > mtx ) ;
if ( ! local - > hw_roc_channel ) {
mutex_unlock ( & local - > mtx ) ;
return ;
}
2010-12-18 17:20:48 +01:00
if ( ! local - > hw_roc_for_tx )
cfg80211_remain_on_channel_expired ( local - > hw_roc_dev ,
local - > hw_roc_cookie ,
local - > hw_roc_channel ,
local - > hw_roc_channel_type ,
GFP_KERNEL ) ;
2010-12-18 17:20:47 +01:00
local - > hw_roc_channel = NULL ;
local - > hw_roc_cookie = 0 ;
ieee80211_recalc_idle ( local ) ;
mutex_unlock ( & local - > mtx ) ;
}
void ieee80211_remain_on_channel_expired ( struct ieee80211_hw * hw )
{
struct ieee80211_local * local = hw_to_local ( hw ) ;
trace_api_remain_on_channel_expired ( local ) ;
ieee80211_queue_work ( hw , & local - > hw_roc_done ) ;
}
EXPORT_SYMBOL_GPL ( ieee80211_remain_on_channel_expired ) ;
void ieee80211_hw_roc_setup ( struct ieee80211_local * local )
{
INIT_WORK ( & local - > hw_roc_start , ieee80211_hw_roc_start ) ;
INIT_WORK ( & local - > hw_roc_done , ieee80211_hw_roc_done ) ;
}