diff options
| author | Johannes Berg <johannes@sipsolutions.net> | 2009-07-09 20:39:48 -0400 |
|---|---|---|
| committer | John W. Linville <linville@tuxdriver.com> | 2009-07-24 15:05:10 -0400 |
| commit | ca386f3137eb68621fadba546d9eb35ac2f82de3 (patch) | |
| tree | bfdb1ecabe0ca942fadec255a7c92ecac405f153 | |
| parent | 01a7e08436929271c6173b5daf3e193ef5b3561a (diff) | |
mac80211: fix multi-use timer
We have, sometimes, multiple things that want to
run but don't have their own timer. Introduce a
new function to mac80211's mlme run_again() that
makes sure that the timer will run again at the
_first_ needed time, use that function and also
properly reprogram the timer once it fired.
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
| -rw-r--r-- | net/mac80211/mlme.c | 40 |
1 files changed, 33 insertions, 7 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 8e4a60497bba..c1114bb8095b 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -72,6 +72,26 @@ static inline void ASSERT_MGD_MTX(struct ieee80211_if_managed *ifmgd) | |||
| 72 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); | 72 | WARN_ON(!mutex_is_locked(&ifmgd->mtx)); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | /* | ||
| 76 | * We can have multiple work items (and connection probing) | ||
| 77 | * scheduling this timer, but we need to take care to only | ||
| 78 | * reschedule it when it should fire _earlier_ than it was | ||
| 79 | * asked for before, or if it's not pending right now. This | ||
| 80 | * function ensures that. Note that it then is required to | ||
| 81 | * run this function for all timeouts after the first one | ||
| 82 | * has happened -- the work that runs from this timer will | ||
| 83 | * do that. | ||
| 84 | */ | ||
| 85 | static void run_again(struct ieee80211_if_managed *ifmgd, | ||
| 86 | unsigned long timeout) | ||
| 87 | { | ||
| 88 | ASSERT_MGD_MTX(ifmgd); | ||
| 89 | |||
| 90 | if (!timer_pending(&ifmgd->timer) || | ||
| 91 | time_before(timeout, ifmgd->timer.expires)) | ||
| 92 | mod_timer(&ifmgd->timer, timeout); | ||
| 93 | } | ||
| 94 | |||
| 75 | static int ecw2cw(int ecw) | 95 | static int ecw2cw(int ecw) |
| 76 | { | 96 | { |
| 77 | return (1 << ecw) - 1; | 97 | return (1 << ecw) - 1; |
| @@ -916,7 +936,7 @@ ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
| 916 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); | 936 | ieee80211_send_probe_req(sdata, NULL, wk->ssid, wk->ssid_len, NULL, 0); |
| 917 | 937 | ||
| 918 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 938 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
| 919 | mod_timer(&ifmgd->timer, wk->timeout); | 939 | run_again(ifmgd, wk->timeout); |
| 920 | 940 | ||
| 921 | return RX_MGMT_NONE; | 941 | return RX_MGMT_NONE; |
| 922 | } | 942 | } |
| @@ -958,7 +978,7 @@ ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | |||
| 958 | wk->auth_transaction = 2; | 978 | wk->auth_transaction = 2; |
| 959 | 979 | ||
| 960 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 980 | wk->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
| 961 | mod_timer(&ifmgd->timer, wk->timeout); | 981 | run_again(ifmgd, wk->timeout); |
| 962 | 982 | ||
| 963 | return RX_MGMT_NONE; | 983 | return RX_MGMT_NONE; |
| 964 | } | 984 | } |
| @@ -1079,7 +1099,7 @@ ieee80211_associate(struct ieee80211_sub_if_data *sdata, | |||
| 1079 | ieee80211_send_assoc(sdata, wk); | 1099 | ieee80211_send_assoc(sdata, wk); |
| 1080 | 1100 | ||
| 1081 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; | 1101 | wk->timeout = jiffies + IEEE80211_ASSOC_TIMEOUT; |
| 1082 | mod_timer(&ifmgd->timer, wk->timeout); | 1102 | run_again(ifmgd, wk->timeout); |
| 1083 | 1103 | ||
| 1084 | return RX_MGMT_NONE; | 1104 | return RX_MGMT_NONE; |
| 1085 | } | 1105 | } |
| @@ -1140,7 +1160,7 @@ void ieee80211_beacon_loss_work(struct work_struct *work) | |||
| 1140 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, | 1160 | ieee80211_send_probe_req(sdata, ifmgd->associated->cbss.bssid, |
| 1141 | ssid + 2, ssid[1], NULL, 0); | 1161 | ssid + 2, ssid[1], NULL, 0); |
| 1142 | 1162 | ||
| 1143 | mod_timer(&ifmgd->timer, jiffies + IEEE80211_PROBE_WAIT); | 1163 | run_again(ifmgd, jiffies + IEEE80211_PROBE_WAIT); |
| 1144 | out: | 1164 | out: |
| 1145 | mutex_unlock(&ifmgd->mtx); | 1165 | mutex_unlock(&ifmgd->mtx); |
| 1146 | } | 1166 | } |
| @@ -1350,8 +1370,7 @@ ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
| 1350 | sdata->dev->name, tu, ms); | 1370 | sdata->dev->name, tu, ms); |
| 1351 | wk->timeout = jiffies + msecs_to_jiffies(ms); | 1371 | wk->timeout = jiffies + msecs_to_jiffies(ms); |
| 1352 | if (ms > IEEE80211_ASSOC_TIMEOUT) | 1372 | if (ms > IEEE80211_ASSOC_TIMEOUT) |
| 1353 | mod_timer(&ifmgd->timer, | 1373 | run_again(ifmgd, jiffies + msecs_to_jiffies(ms)); |
| 1354 | jiffies + msecs_to_jiffies(ms)); | ||
| 1355 | return RX_MGMT_NONE; | 1374 | return RX_MGMT_NONE; |
| 1356 | } | 1375 | } |
| 1357 | 1376 | ||
| @@ -1981,8 +2000,15 @@ static void ieee80211_sta_work(struct work_struct *work) | |||
| 1981 | } | 2000 | } |
| 1982 | 2001 | ||
| 1983 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { | 2002 | list_for_each_entry_safe(wk, tmp, &ifmgd->work_list, list) { |
| 1984 | if (time_before(jiffies, wk->timeout)) | 2003 | if (time_is_after_jiffies(wk->timeout)) { |
| 2004 | /* | ||
| 2005 | * This work item isn't supposed to be worked on | ||
| 2006 | * right now, but take care to adjust the timer | ||
| 2007 | * properly. | ||
| 2008 | */ | ||
| 2009 | run_again(ifmgd, wk->timeout); | ||
| 1985 | continue; | 2010 | continue; |
| 2011 | } | ||
| 1986 | 2012 | ||
| 1987 | switch (wk->state) { | 2013 | switch (wk->state) { |
| 1988 | default: | 2014 | default: |
