|
@@ -2734,3 +2734,44 @@ int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
|
|
|
return ret;
|
|
|
}
|
|
|
EXPORT_SYMBOL(ieee80211_parse_p2p_noa);
|
|
|
+
|
|
|
+void ieee80211_recalc_dtim(struct ieee80211_local *local,
|
|
|
+ struct ieee80211_sub_if_data *sdata)
|
|
|
+{
|
|
|
+ u64 tsf = drv_get_tsf(local, sdata);
|
|
|
+ u64 dtim_count = 0;
|
|
|
+ u16 beacon_int = sdata->vif.bss_conf.beacon_int * 1024;
|
|
|
+ u8 dtim_period = sdata->vif.bss_conf.dtim_period;
|
|
|
+ struct ps_data *ps;
|
|
|
+ u8 bcns_from_dtim;
|
|
|
+
|
|
|
+ if (tsf == -1ULL || !beacon_int || !dtim_period)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
|
|
|
+ sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
|
|
|
+ if (!sdata->bss)
|
|
|
+ return;
|
|
|
+
|
|
|
+ ps = &sdata->bss->ps;
|
|
|
+ } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
|
|
+ ps = &sdata->u.mesh.ps;
|
|
|
+ } else {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * actually finds last dtim_count, mac80211 will update in
|
|
|
+ * __beacon_add_tim().
|
|
|
+ * dtim_count = dtim_period - (tsf / bcn_int) % dtim_period
|
|
|
+ */
|
|
|
+ do_div(tsf, beacon_int);
|
|
|
+ bcns_from_dtim = do_div(tsf, dtim_period);
|
|
|
+ /* just had a DTIM */
|
|
|
+ if (!bcns_from_dtim)
|
|
|
+ dtim_count = 0;
|
|
|
+ else
|
|
|
+ dtim_count = dtim_period - bcns_from_dtim;
|
|
|
+
|
|
|
+ ps->dtim_count = dtim_count;
|
|
|
+}
|