aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-4965.c
diff options
context:
space:
mode:
authorTomas Winkler <tomas.winkler@intel.com>2008-10-24 02:48:49 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-10-31 19:02:23 -0400
commit3fd07a1e5aba89d4be3696c46cb7297f1873195a (patch)
tree48a6c3b68e30136af93c48d35bd1ce08a9237c4d /drivers/net/wireless/iwlwifi/iwl-4965.c
parent8b30b1fe368ab03049435884c11c5c50e4c4ef0b (diff)
iwlwifi: refactor TX response flow
This patch utilize 5000 new TX response command which contains all necessary information and avoids back referencing to the original TX frame. It also change handling of software queue tracking 4965 flow is aligned with changes as much as possible. Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Reviewed-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-4965.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c63
1 files changed, 28 insertions, 35 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index 222c2baa95ca..881bf0472564 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -822,7 +822,6 @@ static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
822 } 822 }
823 823
824 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; 824 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
825 priv->hw_params.first_ampdu_q = IWL49_FIRST_AMPDU_QUEUE;
826 priv->hw_params.max_stations = IWL4965_STATION_COUNT; 825 priv->hw_params.max_stations = IWL4965_STATION_COUNT;
827 priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID; 826 priv->hw_params.bcast_sta_id = IWL4965_BROADCAST_ID;
828 priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE; 827 priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
@@ -2059,7 +2058,7 @@ static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
2059 agg->rate_n_flags = rate_n_flags; 2058 agg->rate_n_flags = rate_n_flags;
2060 agg->bitmap = 0; 2059 agg->bitmap = 0;
2061 2060
2062 /* # frames attempted by Tx command */ 2061 /* num frames attempted by Tx command */
2063 if (agg->frame_count == 1) { 2062 if (agg->frame_count == 1) {
2064 /* Only one frame was attempted; no block-ack will arrive */ 2063 /* Only one frame was attempted; no block-ack will arrive */
2065 status = le16_to_cpu(frame_status[0].status); 2064 status = le16_to_cpu(frame_status[0].status);
@@ -2158,12 +2157,13 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2158 int txq_id = SEQ_TO_QUEUE(sequence); 2157 int txq_id = SEQ_TO_QUEUE(sequence);
2159 int index = SEQ_TO_INDEX(sequence); 2158 int index = SEQ_TO_INDEX(sequence);
2160 struct iwl_tx_queue *txq = &priv->txq[txq_id]; 2159 struct iwl_tx_queue *txq = &priv->txq[txq_id];
2160 struct ieee80211_hdr *hdr;
2161 struct ieee80211_tx_info *info; 2161 struct ieee80211_tx_info *info;
2162 struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; 2162 struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
2163 u32 status = le32_to_cpu(tx_resp->u.status); 2163 u32 status = le32_to_cpu(tx_resp->u.status);
2164 int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION; 2164 int tid = MAX_TID_COUNT;
2165 __le16 fc; 2165 int sta_id;
2166 struct ieee80211_hdr *hdr; 2166 int freed;
2167 u8 *qc = NULL; 2167 u8 *qc = NULL;
2168 2168
2169 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { 2169 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
@@ -2178,8 +2178,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2178 memset(&info->status, 0, sizeof(info->status)); 2178 memset(&info->status, 0, sizeof(info->status));
2179 2179
2180 hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); 2180 hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
2181 fc = hdr->frame_control; 2181 if (ieee80211_is_data_qos(hdr->frame_control)) {
2182 if (ieee80211_is_data_qos(fc)) {
2183 qc = ieee80211_get_qos_ctl(hdr); 2182 qc = ieee80211_get_qos_ctl(hdr);
2184 tid = qc[0] & 0xf; 2183 tid = qc[0] & 0xf;
2185 } 2184 }
@@ -2194,8 +2193,7 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2194 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp); 2193 const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
2195 struct iwl_ht_agg *agg = NULL; 2194 struct iwl_ht_agg *agg = NULL;
2196 2195
2197 if (!qc) 2196 WARN_ON(!qc);
2198 return;
2199 2197
2200 agg = &priv->stations[sta_id].tid[tid].agg; 2198 agg = &priv->stations[sta_id].tid[tid].agg;
2201 2199
@@ -2206,54 +2204,49 @@ static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
2206 info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; 2204 info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
2207 2205
2208 if (txq->q.read_ptr != (scd_ssn & 0xff)) { 2206 if (txq->q.read_ptr != (scd_ssn & 0xff)) {
2209 int freed, ampdu_q;
2210 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); 2207 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
2211 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " 2208 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn "
2212 "%d index %d\n", scd_ssn , index); 2209 "%d index %d\n", scd_ssn , index);
2213 freed = iwl_tx_queue_reclaim(priv, txq_id, index); 2210 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
2214 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 2211 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
2215 2212
2216 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 2213 if (priv->mac80211_registered &&
2217 txq_id >= 0 && priv->mac80211_registered && 2214 (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
2218 agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) { 2215 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
2219 /* calculate mac80211 ampdu sw queue to wake */
2220 ampdu_q = txq_id - IWL49_FIRST_AMPDU_QUEUE +
2221 priv->hw->queues;
2222 if (agg->state == IWL_AGG_OFF) 2216 if (agg->state == IWL_AGG_OFF)
2223 ieee80211_wake_queue(priv->hw, txq_id); 2217 ieee80211_wake_queue(priv->hw, txq_id);
2224 else 2218 else
2225 ieee80211_wake_queue(priv->hw, ampdu_q); 2219 ieee80211_wake_queue(priv->hw,
2220 txq->swq_id);
2226 } 2221 }
2227 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
2228 } 2222 }
2229 } else { 2223 } else {
2230 info->status.rates[0].count = tx_resp->failure_frame + 1; 2224 info->status.rates[0].count = tx_resp->failure_frame + 1;
2231 info->flags |= 2225 info->flags |= iwl_is_tx_success(status) ?
2232 iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; 2226 IEEE80211_TX_STAT_ACK : 0;
2233 iwl_hwrate_to_tx_control(priv, 2227 iwl_hwrate_to_tx_control(priv,
2234 le32_to_cpu(tx_resp->rate_n_flags), 2228 le32_to_cpu(tx_resp->rate_n_flags),
2235 info); 2229 info);
2236 2230
2237 IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags " 2231 IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) "
2238 "0x%x retries %d\n", txq_id, 2232 "rate_n_flags 0x%x retries %d\n",
2239 iwl_get_tx_fail_reason(status), 2233 txq_id,
2240 status, le32_to_cpu(tx_resp->rate_n_flags), 2234 iwl_get_tx_fail_reason(status), status,
2241 tx_resp->failure_frame); 2235 le32_to_cpu(tx_resp->rate_n_flags),
2242 2236 tx_resp->failure_frame);
2243 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index);
2244 2237
2245 if (index != -1) { 2238 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
2246 int freed = iwl_tx_queue_reclaim(priv, txq_id, index); 2239 if (qc)
2247 if (tid != MAX_TID_COUNT)
2248 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 2240 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
2249 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 2241
2250 (txq_id >= 0) && priv->mac80211_registered) 2242 if (priv->mac80211_registered &&
2243 (iwl_queue_space(&txq->q) > txq->q.low_mark))
2251 ieee80211_wake_queue(priv->hw, txq_id); 2244 ieee80211_wake_queue(priv->hw, txq_id);
2252 if (tid != MAX_TID_COUNT)
2253 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
2254 }
2255 } 2245 }
2256 2246
2247 if (qc)
2248 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
2249
2257 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) 2250 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
2258 IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); 2251 IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
2259} 2252}