linux/net/mac80211/pm.c
Johannes Berg 2448798133 mac80211: add driver ops wrappers
In order to later add tracing or verifications to the driver
calls mac80211 makes, this patch adds static inline wrappers
for all operations.

All calls are now written as

	drv_<op>(local, ...);

instead of

	local->ops-><op>(&local->hw, ...);

Where necessary, the wrappers also do existence checking and
return default values as appropriate.

Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
2009-05-06 15:14:37 -04:00

81 lines
2.0 KiB
C

#include <net/mac80211.h>
#include <net/rtnetlink.h>
#include "ieee80211_i.h"
#include "driver-ops.h"
#include "led.h"
int __ieee80211_suspend(struct ieee80211_hw *hw)
{
struct ieee80211_local *local = hw_to_local(hw);
struct ieee80211_sub_if_data *sdata;
struct ieee80211_if_init_conf conf;
struct sta_info *sta;
unsigned long flags;
ieee80211_stop_queues_by_reason(hw,
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
flush_workqueue(local->hw.workqueue);
/* disable keys */
list_for_each_entry(sdata, &local->interfaces, list)
ieee80211_disable_keys(sdata);
/* Tear down aggregation sessions */
rcu_read_lock();
if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
list_for_each_entry_rcu(sta, &local->sta_list, list) {
set_sta_flags(sta, WLAN_STA_SUSPEND);
ieee80211_sta_tear_down_BA_sessions(sta);
}
}
rcu_read_unlock();
/* remove STAs */
if (local->ops->sta_notify) {
spin_lock_irqsave(&local->sta_lock, flags);
list_for_each_entry(sta, &local->sta_list, list) {
if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
sdata = container_of(sdata->bss,
struct ieee80211_sub_if_data,
u.ap);
drv_sta_notify(local, &sdata->vif, STA_NOTIFY_REMOVE,
&sta->sta);
}
spin_unlock_irqrestore(&local->sta_lock, flags);
}
/* remove all interfaces */
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
sdata->vif.type != NL80211_IFTYPE_MONITOR &&
netif_running(sdata->dev)) {
conf.vif = &sdata->vif;
conf.type = sdata->vif.type;
conf.mac_addr = sdata->dev->dev_addr;
drv_remove_interface(local, &conf);
}
}
/* flush again, in case driver queued work */
flush_workqueue(local->hw.workqueue);
/* stop hardware */
if (local->open_count) {
ieee80211_led_radio(local, false);
drv_stop(local);
}
return 0;
}
/*
* __ieee80211_resume() is a static inline which just calls
* ieee80211_reconfig(), which is also needed for hardware
* hang/firmware failure/etc. recovery.
*/