Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 150384
b: refs/heads/master
c: 5bb644a
h: refs/heads/master
v: v3
  • Loading branch information
Johannes Berg authored and John W. Linville committed May 20, 2009
1 parent 7fdcba0 commit b0faa66
Show file tree
Hide file tree
Showing 13 changed files with 322 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: cc32abd494c0a8f76f2638e3f3a76e01c68bc9ea
refs/heads/master: 5bb644a0fd25a5e083ecbfaa92a211db99aa6ef7
29 changes: 29 additions & 0 deletions trunk/net/mac80211/ibss.c
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,9 @@ static void ieee80211_ibss_work(struct work_struct *work)
struct ieee80211_if_ibss *ifibss;
struct sk_buff *skb;

if (WARN_ON(local->suspended))
return;

if (!netif_running(sdata->dev))
return;

Expand Down Expand Up @@ -773,10 +776,36 @@ static void ieee80211_ibss_timer(unsigned long data)
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
struct ieee80211_local *local = sdata->local;

if (local->quiescing) {
ifibss->timer_running = true;
return;
}

set_bit(IEEE80211_IBSS_REQ_RUN, &ifibss->request);
queue_work(local->hw.workqueue, &ifibss->work);
}

#ifdef CONFIG_PM
void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;

cancel_work_sync(&ifibss->work);
if (del_timer_sync(&ifibss->timer))
ifibss->timer_running = true;
}

void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;

if (ifibss->timer_running) {
add_timer(&ifibss->timer);
ifibss->timer_running = false;
}
}
#endif

void ieee80211_ibss_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
Expand Down
26 changes: 26 additions & 0 deletions trunk/net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,7 @@ struct ieee80211_if_managed {
int auth_tries; /* retries for auth req */
int assoc_tries; /* retries for assoc req */

unsigned long timers_running; /* used for quiesce/restart */
bool powersave; /* powersave requested for this iface */

unsigned long request;
Expand Down Expand Up @@ -333,6 +334,9 @@ struct ieee80211_if_ibss {

unsigned long request;
unsigned long last_scan_completed;

bool timer_running;

bool fixed_bssid;
bool fixed_channel;

Expand All @@ -358,6 +362,8 @@ struct ieee80211_if_mesh {
struct timer_list mesh_path_timer;
struct sk_buff_head skb_queue;

unsigned long timers_running;

bool housekeeping;

u8 mesh_id[IEEE80211_MAX_MESH_ID_LEN];
Expand Down Expand Up @@ -609,6 +615,21 @@ struct ieee80211_local {
unsigned int filter_flags; /* FIF_* */
struct iw_statistics wstats;
bool tim_in_locked_section; /* see ieee80211_beacon_get() */

/*
* suspended is true if we finished all the suspend _and_ we have
* not yet come up from resume. This is to be used by mac80211
* to ensure driver sanity during suspend and mac80211's own
* sanity. It can eventually be used for WoW as well.
*/
bool suspended;

/*
* quiescing is true during the suspend process _only_ to
* ease timer cancelling etc.
*/
bool quiescing;

int tx_headroom; /* required headroom for hardware/radiotap */

/* Tasklet and skb queue to process calls from IRQ mode. All frames
Expand Down Expand Up @@ -937,6 +958,8 @@ int ieee80211_max_network_latency(struct notifier_block *nb,
void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct ieee80211_channel_sw_ie *sw_elem,
struct ieee80211_bss *bss);
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata);

/* IBSS code */
void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local);
Expand All @@ -949,6 +972,8 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata,
int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
struct cfg80211_ibss_params *params);
int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_ibss_restart(struct ieee80211_sub_if_data *sdata);

/* scan/BSS handling */
void ieee80211_scan_work(struct work_struct *work);
Expand All @@ -959,6 +984,7 @@ int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
int ieee80211_scan_results(struct ieee80211_local *local,
struct iw_request_info *info,
char *buf, size_t len);
void ieee80211_scan_cancel(struct ieee80211_local *local);
ieee80211_rx_result
ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb,
Expand Down
40 changes: 40 additions & 0 deletions trunk/net/mac80211/mesh.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@
#define CAPAB_OFFSET 17
#define ACCEPT_PLINKS 0x80

#define TMR_RUNNING_HK 0
#define TMR_RUNNING_MP 1

int mesh_allocated;
static struct kmem_cache *rm_cache;

Expand All @@ -45,6 +48,12 @@ static void ieee80211_mesh_housekeeping_timer(unsigned long data)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

ifmsh->housekeeping = true;

if (local->quiescing) {
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
return;
}

queue_work(local->hw.workqueue, &ifmsh->work);
}

Expand Down Expand Up @@ -343,6 +352,11 @@ static void ieee80211_mesh_path_timer(unsigned long data)
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct ieee80211_local *local = sdata->local;

if (local->quiescing) {
set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
return;
}

queue_work(local->hw.workqueue, &ifmsh->work);
}

Expand Down Expand Up @@ -424,6 +438,32 @@ static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata,
round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL));
}

#ifdef CONFIG_PM
void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

/* might restart the timer but that doesn't matter */
cancel_work_sync(&ifmsh->work);

/* use atomic bitops in case both timers fire at the same time */

if (del_timer_sync(&ifmsh->housekeeping_timer))
set_bit(TMR_RUNNING_HK, &ifmsh->timers_running);
if (del_timer_sync(&ifmsh->mesh_path_timer))
set_bit(TMR_RUNNING_MP, &ifmsh->timers_running);
}

void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

if (test_and_clear_bit(TMR_RUNNING_HK, &ifmsh->timers_running))
add_timer(&ifmsh->housekeeping_timer);
if (test_and_clear_bit(TMR_RUNNING_MP, &ifmsh->timers_running))
add_timer(&ifmsh->mesh_path_timer);
}
#endif

void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata)
{
Expand Down
12 changes: 12 additions & 0 deletions trunk/net/mac80211/mesh.h
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,8 @@ void mesh_path_timer(unsigned long data);
void mesh_path_flush_by_nexthop(struct sta_info *sta);
void mesh_path_discard_frame(struct sk_buff *skb,
struct ieee80211_sub_if_data *sdata);
void mesh_path_quiesce(struct ieee80211_sub_if_data *sdata);
void mesh_path_restart(struct ieee80211_sub_if_data *sdata);

#ifdef CONFIG_MAC80211_MESH
extern int mesh_allocated;
Expand Down Expand Up @@ -294,10 +296,20 @@ static inline void mesh_path_activate(struct mesh_path *mpath)

void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local);

void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata);
void mesh_plink_quiesce(struct sta_info *sta);
void mesh_plink_restart(struct sta_info *sta);
#else
#define mesh_allocated 0
static inline void
ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local) {}
static inline void ieee80211_mesh_quiesce(struct ieee80211_sub_if_data *sdata)
{}
static inline void ieee80211_mesh_restart(struct ieee80211_sub_if_data *sdata)
{}
static inline void mesh_plink_quiesce(struct sta_info *sta) {}
static inline void mesh_plink_restart(struct sta_info *sta) {}
#endif

#endif /* IEEE80211S_H */
8 changes: 7 additions & 1 deletion trunk/net/mac80211/mesh_hwmp.c
Original file line number Diff line number Diff line change
Expand Up @@ -836,8 +836,14 @@ void mesh_path_timer(unsigned long data)
mpath = rcu_dereference(mpath);
if (!mpath)
goto endmpathtimer;
spin_lock_bh(&mpath->state_lock);
sdata = mpath->sdata;

if (sdata->local->quiescing) {
rcu_read_unlock();
return;
}

spin_lock_bh(&mpath->state_lock);
if (mpath->flags & MESH_PATH_RESOLVED ||
(!(mpath->flags & MESH_PATH_RESOLVING)))
mpath->flags &= ~(MESH_PATH_RESOLVING | MESH_PATH_RESOLVED);
Expand Down
21 changes: 21 additions & 0 deletions trunk/net/mac80211/mesh_plink.c
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,11 @@ static void mesh_plink_timer(unsigned long data)
*/
sta = (struct sta_info *) data;

if (sta->sdata->local->quiescing) {
sta->plink_timer_was_running = true;
return;
}

spin_lock_bh(&sta->lock);
if (sta->ignore_plink_timer) {
sta->ignore_plink_timer = false;
Expand Down Expand Up @@ -322,6 +327,22 @@ static void mesh_plink_timer(unsigned long data)
}
}

#ifdef CONFIG_PM
void mesh_plink_quiesce(struct sta_info *sta)
{
if (del_timer_sync(&sta->plink_timer))
sta->plink_timer_was_running = true;
}

void mesh_plink_restart(struct sta_info *sta)
{
if (sta->plink_timer_was_running) {
add_timer(&sta->plink_timer);
sta->plink_timer_was_running = false;
}
}
#endif

static inline void mesh_plink_timer_set(struct sta_info *sta, int timeout)
{
sta->plink_timer.expires = jiffies + (HZ * timeout / 1000);
Expand Down
59 changes: 59 additions & 0 deletions trunk/net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#define IEEE80211_PROBE_IDLE_TIME (60 * HZ)
#define IEEE80211_RETRY_AUTH_INTERVAL (1 * HZ)

#define TMR_RUNNING_TIMER 0
#define TMR_RUNNING_CHANSW 1

/* utils */
static int ecw2cw(int ecw)
{
Expand Down Expand Up @@ -521,6 +524,11 @@ static void ieee80211_chswitch_timer(unsigned long data)
(struct ieee80211_sub_if_data *) data;
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

if (sdata->local->quiescing) {
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
return;
}

queue_work(sdata->local->hw.workqueue, &ifmgd->chswitch_work);
}

Expand Down Expand Up @@ -714,6 +722,9 @@ void ieee80211_dynamic_ps_timer(unsigned long data)
{
struct ieee80211_local *local = (void *) data;

if (local->quiescing)
return;

queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work);
}

Expand Down Expand Up @@ -2108,6 +2119,11 @@ static void ieee80211_sta_timer(unsigned long data)
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;

if (local->quiescing) {
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);
return;
}

set_bit(IEEE80211_STA_REQ_RUN, &ifmgd->request);
queue_work(local->hw.workqueue, &ifmgd->work);
}
Expand Down Expand Up @@ -2240,6 +2256,17 @@ static void ieee80211_sta_work(struct work_struct *work)

if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
return;

/*
* Nothing should have been stuffed into the workqueue during
* the suspend->resume cycle. If this WARN is seen then there
* is a bug with either the driver suspend or something in
* mac80211 stuffing into the workqueue which we haven't yet
* cleared during mac80211's suspend cycle.
*/
if (WARN_ON(local->suspended))
return;

ifmgd = &sdata->u.mgd;

while ((skb = skb_dequeue(&ifmgd->skb_queue)))
Expand Down Expand Up @@ -2307,6 +2334,38 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata)
}
}

#ifdef CONFIG_PM
void ieee80211_sta_quiesce(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

/*
* we need to use atomic bitops for the running bits
* only because both timers might fire at the same
* time -- the code here is properly synchronised.
*/

cancel_work_sync(&ifmgd->work);
cancel_work_sync(&ifmgd->beacon_loss_work);
if (del_timer_sync(&ifmgd->timer))
set_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running);

cancel_work_sync(&ifmgd->chswitch_work);
if (del_timer_sync(&ifmgd->chswitch_timer))
set_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running);
}

void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;

if (test_and_clear_bit(TMR_RUNNING_TIMER, &ifmgd->timers_running))
add_timer(&ifmgd->timer);
if (test_and_clear_bit(TMR_RUNNING_CHANSW, &ifmgd->timers_running))
add_timer(&ifmgd->chswitch_timer);
}
#endif

/* interface setup */
void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
{
Expand Down
Loading

0 comments on commit b0faa66

Please sign in to comment.