* Flags to define PHY configuration options
*
* @IEEE80211_CONF_RADIOTAP: add radiotap header at receive time (if supported)
- * @IEEE80211_CONF_PS: Enable 802.11 power save mode
+ * @IEEE80211_CONF_PS: Enable 802.11 power save mode (managed mode only)
*/
enum ieee80211_conf_flags {
IEEE80211_CONF_RADIOTAP = (1<<0),
*
* This struct indicates how the driver shall configure the hardware.
*
+ * @flags: configuration flags defined above
+ *
* @radio_enabled: when zero, driver is required to switch off the radio.
* @beacon_int: beacon interval (TODO make interface config)
+ *
* @listen_interval: listen interval in units of beacon interval
- * @flags: configuration flags defined above
+ * @max_sleep_interval: the maximum number of beacon intervals to sleep for
+ * before checking the beacon for a TIM bit (managed mode only); this
+ * value will be only achievable between DTIM frames, the hardware
+ * needs to check for the multicast traffic bit in DTIM beacons.
+ * This variable is valid only when the CONF_PS flag is set.
+ * @dynamic_ps_timeout: The dynamic powersave timeout (in ms), see the
+ * powersave documentation below. This variable is valid only when
+ * the CONF_PS flag is set.
+ *
* @power_level: requested transmit power (in dBm)
- * @dynamic_ps_timeout: dynamic powersave timeout (in ms)
+ *
* @channel: the channel to tune to
* @channel_type: the channel (HT) type
+ *
* @long_frame_max_tx_count: Maximum number of transmissions for a "long" frame
* (a frame not RTS protected), called "dot11LongRetryLimit" in 802.11,
* but actually means the number of transmissions not the number of retries
int beacon_int;
u32 flags;
int power_level, dynamic_ps_timeout;
+ int max_sleep_interval;
u16 listen_interval;
bool radio_enabled;
beaconint_us = ieee80211_tu_to_usec(
found->vif.bss_conf.beacon_int);
- if (beaconint_us > latency)
+ if (beaconint_us > latency) {
local->ps_sdata = NULL;
- else
+ } else {
+ u8 dtimper = found->vif.bss_conf.dtim_period;
+ int maxslp = 1;
+
+ if (dtimper > 1)
+ maxslp = min_t(int, dtimper,
+ latency / beaconint_us);
+
+ local->hw.conf.max_sleep_interval = maxslp;
local->ps_sdata = found;
+ }
} else {
local->ps_sdata = NULL;
}
ieee80211_bss_info_change_notify(sdata, bss_info_changed);
/* will be same as sdata */
- if (local->ps_sdata)
- ieee80211_enable_ps(local, sdata);
+ if (local->ps_sdata) {
+ mutex_lock(&local->iflist_mtx);
+ ieee80211_recalc_ps(local, -1);
+ mutex_unlock(&local->iflist_mtx);
+ }
netif_tx_start_all_queues(sdata->dev);
netif_carrier_on(sdata->dev);