Commit 4571d3bf authored by Christian Lamparter's avatar Christian Lamparter Committed by John W. Linville

mac80211: add sta_notify_ps callback

This patch is necessary in order to provide a proper Access point support for p54.
Unfortunately for us, there is no documented way to disable the interfering
power save buffering mechanism in firmware completely.

Therefore we give in and notify the driver through our new sta_notify_ps callback,
so that we can update the filter state.
Signed-off-by: default avatarChristian Lamparter <chunkeey@web.de>
Acked-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 2a163c6d
...@@ -781,6 +781,19 @@ enum sta_notify_cmd { ...@@ -781,6 +781,19 @@ enum sta_notify_cmd {
STA_NOTIFY_ADD, STA_NOTIFY_REMOVE STA_NOTIFY_ADD, STA_NOTIFY_REMOVE
}; };
/**
* enum sta_notify_ps_cmd - sta power save notify command
*
* Used with the sta_notify_ps() callback in &struct ieee80211_ops to
* notify the driver if a station made a power state transition.
*
* @STA_NOTIFY_SLEEP: a station is now sleeping
* @STA_NOTIFY_AWAKE: a sleeping station woke up
*/
enum sta_notify_ps_cmd {
STA_NOTIFY_SLEEP, STA_NOTIFY_AWAKE,
};
/** /**
* enum ieee80211_tkip_key_type - get tkip key * enum ieee80211_tkip_key_type - get tkip key
* *
...@@ -1251,6 +1264,9 @@ enum ieee80211_ampdu_mlme_action { ...@@ -1251,6 +1264,9 @@ enum ieee80211_ampdu_mlme_action {
* @sta_notify: Notifies low level driver about addition or removal * @sta_notify: Notifies low level driver about addition or removal
* of associated station or AP. * of associated station or AP.
* *
* @sta_ps_notify: Notifies low level driver about the power state transition
* of a associated station. Must be atomic.
*
* @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max), * @conf_tx: Configure TX queue parameters (EDCF (aifs, cw_min, cw_max),
* bursting) for a hardware TX queue. * bursting) for a hardware TX queue.
* *
...@@ -1317,6 +1333,8 @@ struct ieee80211_ops { ...@@ -1317,6 +1333,8 @@ struct ieee80211_ops {
int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value); int (*set_frag_threshold)(struct ieee80211_hw *hw, u32 value);
void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif, void (*sta_notify)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
enum sta_notify_cmd, struct ieee80211_sta *sta); enum sta_notify_cmd, struct ieee80211_sta *sta);
void (*sta_notify_ps)(struct ieee80211_hw *hw,
enum sta_notify_ps_cmd, struct ieee80211_sta *sta);
int (*conf_tx)(struct ieee80211_hw *hw, u16 queue, int (*conf_tx)(struct ieee80211_hw *hw, u16 queue,
const struct ieee80211_tx_queue_params *params); const struct ieee80211_tx_queue_params *params);
int (*get_tx_stats)(struct ieee80211_hw *hw, int (*get_tx_stats)(struct ieee80211_hw *hw,
......
...@@ -654,9 +654,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx) ...@@ -654,9 +654,13 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
static void ap_sta_ps_start(struct sta_info *sta) static void ap_sta_ps_start(struct sta_info *sta)
{ {
struct ieee80211_sub_if_data *sdata = sta->sdata; struct ieee80211_sub_if_data *sdata = sta->sdata;
struct ieee80211_local *local = sdata->local;
atomic_inc(&sdata->bss->num_sta_ps); atomic_inc(&sdata->bss->num_sta_ps);
set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL); set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
if (local->ops->sta_notify_ps)
local->ops->sta_notify_ps(local_to_hw(local), STA_NOTIFY_SLEEP,
&sta->sta);
#ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n", printk(KERN_DEBUG "%s: STA %pM aid %d enters power save mode\n",
sdata->dev->name, sta->sta.addr, sta->sta.aid); sdata->dev->name, sta->sta.addr, sta->sta.aid);
...@@ -673,6 +677,9 @@ static int ap_sta_ps_end(struct sta_info *sta) ...@@ -673,6 +677,9 @@ static int ap_sta_ps_end(struct sta_info *sta)
atomic_dec(&sdata->bss->num_sta_ps); atomic_dec(&sdata->bss->num_sta_ps);
clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL); clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
if (local->ops->sta_notify_ps)
local->ops->sta_notify_ps(local_to_hw(local), STA_NOTIFY_AWAKE,
&sta->sta);
if (!skb_queue_empty(&sta->ps_tx_buf)) if (!skb_queue_empty(&sta->ps_tx_buf))
sta_info_clear_tim_bit(sta); sta_info_clear_tim_bit(sta);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment