From 3e56eadfb6a1f28d753afa9fe27296258ae240e5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 15 Feb 2013 22:23:18 +0100 Subject: iwlwifi: mvm: implement AP/GO uAPSD support Newer firmware will support uAPSD clients in AP/GO mode, so complete the driver support for it. The way it works is described in comments in the code, but basically the driver just has to pass down all the mac80211 requests and do accounting on agg/non-agg queues properly. For older firmware, this doesn't change anything as it ignores the fields used by the new firmware, and we only advertise uAPSD support when the firmware does. Signed-off-by: Johannes Berg Signed-off-by: Emmanuel Grumbach --- drivers/net/wireless/iwlwifi/mvm/tx.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'drivers/net/wireless/iwlwifi/mvm/tx.c') diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index 90378c2..8d18bf2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -377,6 +377,13 @@ int iwl_mvm_tx_skb(struct iwl_mvm *mvm, struct sk_buff *skb, tx_cmd = (struct iwl_tx_cmd *)dev_cmd->payload; /* From now on, we cannot access info->control */ + /* + * we handle that entirely ourselves -- for uAPSD the firmware + * will always send a notification, and for PS-Poll responses + * we'll notify mac80211 when getting frame status + */ + info->flags &= ~IEEE80211_TX_STATUS_EOSP; + spin_lock(&mvmsta->lock); if (ieee80211_is_data_qos(fc) && !ieee80211_is_qos_nullfunc(fc)) { @@ -437,6 +444,17 @@ static void iwl_mvm_check_ratid_empty(struct iwl_mvm *mvm, lockdep_assert_held(&mvmsta->lock); + if ((tid_data->state == IWL_AGG_ON || + tid_data->state == IWL_EMPTYING_HW_QUEUE_DELBA) && + iwl_mvm_tid_queued(tid_data) == 0) { + /* + * Now that this aggregation queue is empty tell mac80211 so it + * knows we no longer have frames buffered for the station on + * this TID (for the TIM bitmap calculation.) + */ + ieee80211_sta_set_buffered(sta, tid, false); + } + if (tid_data->ssn != tid_data->next_reclaimed) return; @@ -674,6 +692,11 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm, iwl_mvm_check_ratid_empty(mvm, sta, tid); spin_unlock_bh(&mvmsta->lock); } + + if (mvmsta->next_status_eosp) { + mvmsta->next_status_eosp = false; + ieee80211_sta_eosp(sta); + } } else { sta = NULL; mvmsta = NULL; -- cgit v1.1