|
43 | 43 | #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
|
44 | 44 | #define IEEE80211_ASSOC_MAX_TRIES 3
|
45 | 45 |
|
| 46 | +#define IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS msecs_to_jiffies(100) |
| 47 | +#define IEEE80211_ADV_TTLM_ST_UNDERFLOW 0xff00 |
| 48 | + |
46 | 49 | static int max_nullfunc_tries = 2;
|
47 | 50 | module_param(max_nullfunc_tries, int, 0644);
|
48 | 51 | MODULE_PARM_DESC(max_nullfunc_tries,
|
@@ -5964,6 +5967,13 @@ ieee80211_parse_adv_t2l(struct ieee80211_sub_if_data *sdata,
|
5964 | 5967 | pos++;
|
5965 | 5968 |
|
5966 | 5969 | ttlm_info->switch_time = get_unaligned_le16(pos);
|
| 5970 | + |
| 5971 | + /* Since ttlm_info->switch_time == 0 means no switch time, bump it |
| 5972 | + * by 1. |
| 5973 | + */ |
| 5974 | + if (!ttlm_info->switch_time) |
| 5975 | + ttlm_info->switch_time = 1; |
| 5976 | + |
5967 | 5977 | pos += 2;
|
5968 | 5978 |
|
5969 | 5979 | if (control & IEEE80211_TTLM_CONTROL_EXPECTED_DUR_PRESENT) {
|
@@ -6058,25 +6068,46 @@ static void ieee80211_process_adv_ttlm(struct ieee80211_sub_if_data *sdata,
|
6058 | 6068 | }
|
6059 | 6069 |
|
6060 | 6070 | if (ttlm_info.switch_time) {
|
6061 |
| - u32 st_us, delay = 0; |
6062 |
| - u32 ts_l26 = beacon_ts & GENMASK(25, 0); |
| 6071 | + u16 beacon_ts_tu, st_tu, delay; |
| 6072 | + u32 delay_jiffies; |
| 6073 | + u64 mask; |
6063 | 6074 |
|
6064 | 6075 | /* The t2l map switch time is indicated with a partial
|
6065 |
| - * TSF value, convert it to TSF and calc the delay |
6066 |
| - * to the start time. |
| 6076 | + * TSF value (bits 10 to 25), get the partial beacon TS |
| 6077 | + * as well, and calc the delay to the start time. |
| 6078 | + */ |
| 6079 | + mask = GENMASK_ULL(25, 10); |
| 6080 | + beacon_ts_tu = (beacon_ts & mask) >> 10; |
| 6081 | + st_tu = ttlm_info.switch_time; |
| 6082 | + delay = st_tu - beacon_ts_tu; |
| 6083 | + |
| 6084 | + /* |
| 6085 | + * If the switch time is far in the future, then it |
| 6086 | + * could also be the previous switch still being |
| 6087 | + * announced. |
| 6088 | + * We can simply ignore it for now, if it is a future |
| 6089 | + * switch the AP will continue to announce it anyway. |
| 6090 | + */ |
| 6091 | + if (delay > IEEE80211_ADV_TTLM_ST_UNDERFLOW) |
| 6092 | + return; |
| 6093 | + |
| 6094 | + delay_jiffies = TU_TO_JIFFIES(delay); |
| 6095 | + |
| 6096 | + /* Link switching can take time, so schedule it |
| 6097 | + * 100ms before to be ready on time |
6067 | 6098 | */
|
6068 |
| - st_us = ieee80211_tu_to_usec(ttlm_info.switch_time); |
6069 |
| - if (st_us > ts_l26) |
6070 |
| - delay = st_us - ts_l26; |
| 6099 | + if (delay_jiffies > IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS) |
| 6100 | + delay_jiffies -= |
| 6101 | + IEEE80211_ADV_TTLM_SAFETY_BUFFER_MS; |
6071 | 6102 | else
|
6072 |
| - continue; |
| 6103 | + delay_jiffies = 0; |
6073 | 6104 |
|
6074 | 6105 | sdata->u.mgd.ttlm_info = ttlm_info;
|
6075 | 6106 | wiphy_delayed_work_cancel(sdata->local->hw.wiphy,
|
6076 | 6107 | &sdata->u.mgd.ttlm_work);
|
6077 | 6108 | wiphy_delayed_work_queue(sdata->local->hw.wiphy,
|
6078 | 6109 | &sdata->u.mgd.ttlm_work,
|
6079 |
| - usecs_to_jiffies(delay)); |
| 6110 | + delay_jiffies); |
6080 | 6111 | return;
|
6081 | 6112 | }
|
6082 | 6113 | }
|
|
0 commit comments