diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/dvm')
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/agn.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/lib.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/tx.c | 45 |
4 files changed, 58 insertions, 5 deletions
diff --git a/drivers/net/wireless/iwlwifi/dvm/agn.h b/drivers/net/wireless/iwlwifi/dvm/agn.h index 76b762e48703..e575b9b0cda8 100644 --- a/drivers/net/wireless/iwlwifi/dvm/agn.h +++ b/drivers/net/wireless/iwlwifi/dvm/agn.h | |||
@@ -178,7 +178,7 @@ int iwlagn_hw_valid_rtc_data_addr(u32 addr); | |||
178 | /* lib */ | 178 | /* lib */ |
179 | int iwlagn_send_tx_power(struct iwl_priv *priv); | 179 | int iwlagn_send_tx_power(struct iwl_priv *priv); |
180 | void iwlagn_temperature(struct iwl_priv *priv); | 180 | void iwlagn_temperature(struct iwl_priv *priv); |
181 | int iwlagn_txfifo_flush(struct iwl_priv *priv); | 181 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk); |
182 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv); | 182 | void iwlagn_dev_txfifo_flush(struct iwl_priv *priv); |
183 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); | 183 | int iwlagn_send_beacon_cmd(struct iwl_priv *priv); |
184 | int iwl_send_statistics_request(struct iwl_priv *priv, | 184 | int iwl_send_statistics_request(struct iwl_priv *priv, |
@@ -212,6 +212,8 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
212 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); | 212 | struct ieee80211_sta *sta, u16 tid, u8 buf_size); |
213 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, | 213 | int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, |
214 | struct ieee80211_sta *sta, u16 tid); | 214 | struct ieee80211_sta *sta, u16 tid); |
215 | int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
216 | struct ieee80211_sta *sta, u16 tid); | ||
215 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | 217 | int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, |
216 | struct iwl_rx_cmd_buffer *rxb, | 218 | struct iwl_rx_cmd_buffer *rxb, |
217 | struct iwl_device_cmd *cmd); | 219 | struct iwl_device_cmd *cmd); |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index f2aeb1a8aa01..29ff93f9656e 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -136,7 +136,7 @@ int iwlagn_manage_ibss_station(struct iwl_priv *priv, | |||
136 | * 1. acquire mutex before calling | 136 | * 1. acquire mutex before calling |
137 | * 2. make sure rf is on and not in exit state | 137 | * 2. make sure rf is on and not in exit state |
138 | */ | 138 | */ |
139 | int iwlagn_txfifo_flush(struct iwl_priv *priv) | 139 | int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk) |
140 | { | 140 | { |
141 | struct iwl_txfifo_flush_cmd flush_cmd; | 141 | struct iwl_txfifo_flush_cmd flush_cmd; |
142 | struct iwl_host_cmd cmd = { | 142 | struct iwl_host_cmd cmd = { |
@@ -162,6 +162,9 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv) | |||
162 | if (priv->nvm_data->sku_cap_11n_enable) | 162 | if (priv->nvm_data->sku_cap_11n_enable) |
163 | flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; | 163 | flush_cmd.queue_control |= IWL_AGG_TX_QUEUE_MSK; |
164 | 164 | ||
165 | if (scd_q_msk) | ||
166 | flush_cmd.queue_control = cpu_to_le32(scd_q_msk); | ||
167 | |||
165 | IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", | 168 | IWL_DEBUG_INFO(priv, "queue control: 0x%x\n", |
166 | flush_cmd.queue_control); | 169 | flush_cmd.queue_control); |
167 | flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); | 170 | flush_cmd.flush_control = cpu_to_le16(IWL_DROP_ALL); |
@@ -173,7 +176,7 @@ void iwlagn_dev_txfifo_flush(struct iwl_priv *priv) | |||
173 | { | 176 | { |
174 | mutex_lock(&priv->mutex); | 177 | mutex_lock(&priv->mutex); |
175 | ieee80211_stop_queues(priv->hw); | 178 | ieee80211_stop_queues(priv->hw); |
176 | if (iwlagn_txfifo_flush(priv)) { | 179 | if (iwlagn_txfifo_flush(priv, 0)) { |
177 | IWL_ERR(priv, "flush request fail\n"); | 180 | IWL_ERR(priv, "flush request fail\n"); |
178 | goto done; | 181 | goto done; |
179 | } | 182 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index a7294fa4d7e5..fc3879804622 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -777,9 +777,12 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw, | |||
777 | IWL_DEBUG_HT(priv, "start Tx\n"); | 777 | IWL_DEBUG_HT(priv, "start Tx\n"); |
778 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); | 778 | ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); |
779 | break; | 779 | break; |
780 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
781 | case IEEE80211_AMPDU_TX_STOP_FLUSH: | 780 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
782 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: | 781 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
782 | IWL_DEBUG_HT(priv, "Flush Tx\n"); | ||
783 | ret = iwlagn_tx_agg_flush(priv, vif, sta, tid); | ||
784 | break; | ||
785 | case IEEE80211_AMPDU_TX_STOP_CONT: | ||
783 | IWL_DEBUG_HT(priv, "stop Tx\n"); | 786 | IWL_DEBUG_HT(priv, "stop Tx\n"); |
784 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); | 787 | ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); |
785 | if ((ret == 0) && (priv->agg_tids_count > 0)) { | 788 | if ((ret == 0) && (priv->agg_tids_count > 0)) { |
@@ -1122,7 +1125,7 @@ static void iwlagn_mac_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
1122 | */ | 1125 | */ |
1123 | if (drop) { | 1126 | if (drop) { |
1124 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); | 1127 | IWL_DEBUG_MAC80211(priv, "send flush command\n"); |
1125 | if (iwlagn_txfifo_flush(priv)) { | 1128 | if (iwlagn_txfifo_flush(priv, 0)) { |
1126 | IWL_ERR(priv, "flush request fail\n"); | 1129 | IWL_ERR(priv, "flush request fail\n"); |
1127 | goto done; | 1130 | goto done; |
1128 | } | 1131 | } |
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c index cc1e0c1a6f48..2c9e9897a3f1 100644 --- a/drivers/net/wireless/iwlwifi/dvm/tx.c +++ b/drivers/net/wireless/iwlwifi/dvm/tx.c | |||
@@ -674,6 +674,51 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif, | |||
674 | return ret; | 674 | return ret; |
675 | } | 675 | } |
676 | 676 | ||
677 | int iwlagn_tx_agg_flush(struct iwl_priv *priv, struct ieee80211_vif *vif, | ||
678 | struct ieee80211_sta *sta, u16 tid) | ||
679 | { | ||
680 | struct iwl_tid_data *tid_data; | ||
681 | enum iwl_agg_state agg_state; | ||
682 | int sta_id, txq_id; | ||
683 | sta_id = iwl_sta_id(sta); | ||
684 | |||
685 | /* | ||
686 | * First set the agg state to OFF to avoid calling | ||
687 | * ieee80211_stop_tx_ba_cb in iwlagn_check_ratid_empty. | ||
688 | */ | ||
689 | spin_lock_bh(&priv->sta_lock); | ||
690 | |||
691 | tid_data = &priv->tid_data[sta_id][tid]; | ||
692 | txq_id = tid_data->agg.txq_id; | ||
693 | agg_state = tid_data->agg.state; | ||
694 | IWL_DEBUG_TX_QUEUES(priv, "Flush AGG: sta %d tid %d q %d state %d\n", | ||
695 | sta_id, tid, txq_id, tid_data->agg.state); | ||
696 | |||
697 | tid_data->agg.state = IWL_AGG_OFF; | ||
698 | |||
699 | spin_unlock_bh(&priv->sta_lock); | ||
700 | |||
701 | if (iwlagn_txfifo_flush(priv, BIT(txq_id))) | ||
702 | IWL_ERR(priv, "Couldn't flush the AGG queue\n"); | ||
703 | |||
704 | if (test_bit(txq_id, priv->agg_q_alloc)) { | ||
705 | /* | ||
706 | * If the transport didn't know that we wanted to start | ||
707 | * agreggation, don't tell it that we want to stop them. | ||
708 | * This can happen when we don't get the addBA response on | ||
709 | * time, or we hadn't time to drain the AC queues. | ||
710 | */ | ||
711 | if (agg_state == IWL_AGG_ON) | ||
712 | iwl_trans_txq_disable(priv->trans, txq_id); | ||
713 | else | ||
714 | IWL_DEBUG_TX_QUEUES(priv, "Don't disable tx agg: %d\n", | ||
715 | agg_state); | ||
716 | iwlagn_dealloc_agg_txq(priv, txq_id); | ||
717 | } | ||
718 | |||
719 | return 0; | ||
720 | } | ||
721 | |||
677 | int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, | 722 | int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, |
678 | struct ieee80211_sta *sta, u16 tid, u8 buf_size) | 723 | struct ieee80211_sta *sta, u16 tid, u8 buf_size) |
679 | { | 724 | { |