aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-5000.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-5000.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-5000.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c81
1 files changed, 34 insertions, 47 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index ad566ef233b8..a8c8c858e209 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -683,7 +683,7 @@ static void iwl5000_tx_queue_set_status(struct iwl_priv *priv,
683 int tx_fifo_id, int scd_retry) 683 int tx_fifo_id, int scd_retry)
684{ 684{
685 int txq_id = txq->q.id; 685 int txq_id = txq->q.id;
686 int active = test_bit(txq_id, &priv->txq_ctx_active_msk)?1:0; 686 int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
687 687
688 iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id), 688 iwl_write_prph(priv, IWL50_SCD_QUEUE_STATUS_BITS(txq_id),
689 (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) | 689 (active << IWL50_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
@@ -801,7 +801,6 @@ static int iwl5000_hw_set_hw_params(struct iwl_priv *priv)
801 } 801 }
802 802
803 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues; 803 priv->hw_params.max_txq_num = priv->cfg->mod_params->num_of_queues;
804 priv->hw_params.first_ampdu_q = IWL50_FIRST_AMPDU_QUEUE;
805 priv->hw_params.max_stations = IWL5000_STATION_COUNT; 804 priv->hw_params.max_stations = IWL5000_STATION_COUNT;
806 priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID; 805 priv->hw_params.bcast_sta_id = IWL5000_BROADCAST_ID;
807 priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE; 806 priv->hw_params.max_data_size = IWL50_RTC_DATA_SIZE;
@@ -1159,7 +1158,7 @@ static int iwl5000_tx_status_reply_tx(struct iwl_priv *priv,
1159 info->status.rates[0].count = tx_resp->failure_frame + 1; 1158 info->status.rates[0].count = tx_resp->failure_frame + 1;
1160 info->flags &= ~IEEE80211_TX_CTL_AMPDU; 1159 info->flags &= ~IEEE80211_TX_CTL_AMPDU;
1161 info->flags |= iwl_is_tx_success(status)? 1160 info->flags |= iwl_is_tx_success(status)?
1162 IEEE80211_TX_STAT_ACK : 0; 1161 IEEE80211_TX_STAT_ACK : 0;
1163 iwl_hwrate_to_tx_control(priv, rate_n_flags, info); 1162 iwl_hwrate_to_tx_control(priv, rate_n_flags, info);
1164 1163
1165 /* FIXME: code repetition end */ 1164 /* FIXME: code repetition end */
@@ -1245,9 +1244,9 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1245 struct ieee80211_tx_info *info; 1244 struct ieee80211_tx_info *info;
1246 struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; 1245 struct iwl5000_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
1247 u32 status = le16_to_cpu(tx_resp->status.status); 1246 u32 status = le16_to_cpu(tx_resp->status.status);
1248 int tid = MAX_TID_COUNT, sta_id = IWL_INVALID_STATION; 1247 int tid;
1249 struct ieee80211_hdr *hdr; 1248 int sta_id;
1250 u8 *qc = NULL; 1249 int freed;
1251 1250
1252 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) { 1251 if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
1253 IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " 1252 IWL_ERROR("Read index for DMA queue txq_id (%d) index %d "
@@ -1260,25 +1259,13 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1260 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); 1259 info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]);
1261 memset(&info->status, 0, sizeof(info->status)); 1260 memset(&info->status, 0, sizeof(info->status));
1262 1261
1263 hdr = iwl_tx_queue_get_hdr(priv, txq_id, index); 1262 tid = (tx_resp->ra_tid & IWL50_TX_RES_TID_MSK) >> IWL50_TX_RES_TID_POS;
1264 if (ieee80211_is_data_qos(hdr->frame_control)) { 1263 sta_id = (tx_resp->ra_tid & IWL50_TX_RES_RA_MSK) >> IWL50_TX_RES_RA_POS;
1265 qc = ieee80211_get_qos_ctl(hdr);
1266 tid = qc[0] & 0xf;
1267 }
1268
1269 sta_id = iwl_get_ra_sta_id(priv, hdr);
1270 if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
1271 IWL_ERROR("Station not known\n");
1272 return;
1273 }
1274 1264
1275 if (txq->sched_retry) { 1265 if (txq->sched_retry) {
1276 const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp); 1266 const u32 scd_ssn = iwl5000_get_scd_ssn(tx_resp);
1277 struct iwl_ht_agg *agg = NULL; 1267 struct iwl_ht_agg *agg = NULL;
1278 1268
1279 if (!qc)
1280 return;
1281
1282 agg = &priv->stations[sta_id].tid[tid].agg; 1269 agg = &priv->stations[sta_id].tid[tid].agg;
1283 1270
1284 iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index); 1271 iwl5000_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
@@ -1288,53 +1275,53 @@ static void iwl5000_rx_reply_tx(struct iwl_priv *priv,
1288 info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK; 1275 info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
1289 1276
1290 if (txq->q.read_ptr != (scd_ssn & 0xff)) { 1277 if (txq->q.read_ptr != (scd_ssn & 0xff)) {
1291 int freed, ampdu_q;
1292 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd); 1278 index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
1293 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim scd_ssn " 1279 IWL_DEBUG_TX_REPLY("Retry scheduler reclaim "
1294 "%d index %d\n", scd_ssn , index); 1280 "scd_ssn=%d idx=%d txq=%d swq=%d\n",
1281 scd_ssn , index, txq_id, txq->swq_id);
1282
1295 freed = iwl_tx_queue_reclaim(priv, txq_id, index); 1283 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
1296 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 1284 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
1297 1285
1298 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 1286 if (priv->mac80211_registered &&
1299 txq_id >= 0 && priv->mac80211_registered && 1287 (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
1300 agg->state != IWL_EMPTYING_HW_QUEUE_DELBA) { 1288 (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)) {
1301 /* calculate mac80211 ampdu sw queue to wake */
1302 ampdu_q = txq_id - IWL50_FIRST_AMPDU_QUEUE +
1303 priv->hw->queues;
1304 if (agg->state == IWL_AGG_OFF) 1289 if (agg->state == IWL_AGG_OFF)
1305 ieee80211_wake_queue(priv->hw, txq_id); 1290 ieee80211_wake_queue(priv->hw, txq_id);
1306 else 1291 else
1307 ieee80211_wake_queue(priv->hw, ampdu_q); 1292 ieee80211_wake_queue(priv->hw,
1293 txq->swq_id);
1308 } 1294 }
1309 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
1310 } 1295 }
1311 } else { 1296 } else {
1297 BUG_ON(txq_id != txq->swq_id);
1298
1312 info->status.rates[0].count = tx_resp->failure_frame + 1; 1299 info->status.rates[0].count = tx_resp->failure_frame + 1;
1313 info->flags = 1300 info->flags |= iwl_is_tx_success(status) ?
1314 iwl_is_tx_success(status) ? IEEE80211_TX_STAT_ACK : 0; 1301 IEEE80211_TX_STAT_ACK : 0;
1315 iwl_hwrate_to_tx_control(priv, 1302 iwl_hwrate_to_tx_control(priv,
1316 le32_to_cpu(tx_resp->rate_n_flags), 1303 le32_to_cpu(tx_resp->rate_n_flags),
1317 info); 1304 info);
1318 1305
1319 IWL_DEBUG_TX("Tx queue %d Status %s (0x%08x) rate_n_flags " 1306 IWL_DEBUG_TX_REPLY("TXQ %d status %s (0x%08x) rate_n_flags "
1320 "0x%x retries %d\n", txq_id, 1307 "0x%x retries %d\n",
1321 iwl_get_tx_fail_reason(status), 1308 txq_id,
1322 status, le32_to_cpu(tx_resp->rate_n_flags), 1309 iwl_get_tx_fail_reason(status), status,
1323 tx_resp->failure_frame); 1310 le32_to_cpu(tx_resp->rate_n_flags),
1311 tx_resp->failure_frame);
1324 1312
1325 IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); 1313 freed = iwl_tx_queue_reclaim(priv, txq_id, index);
1326 if (index != -1) { 1314 if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
1327 int freed = iwl_tx_queue_reclaim(priv, txq_id, index);
1328 if (tid != MAX_TID_COUNT)
1329 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed; 1315 priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
1330 if (iwl_queue_space(&txq->q) > txq->q.low_mark && 1316
1331 (txq_id >= 0) && priv->mac80211_registered) 1317 if (priv->mac80211_registered &&
1318 (iwl_queue_space(&txq->q) > txq->q.low_mark))
1332 ieee80211_wake_queue(priv->hw, txq_id); 1319 ieee80211_wake_queue(priv->hw, txq_id);
1333 if (tid != MAX_TID_COUNT)
1334 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
1335 }
1336 } 1320 }
1337 1321
1322 if (ieee80211_is_data_qos(tx_resp->frame_ctrl))
1323 iwl_txq_check_empty(priv, sta_id, tid, txq_id);
1324
1338 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK)) 1325 if (iwl_check_bits(status, TX_ABORT_REQUIRED_MSK))
1339 IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n"); 1326 IWL_ERROR("TODO: Implement Tx ABORT REQUIRED!!!\n");
1340} 1327}