diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-3945.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-3945.c | 65 |
1 files changed, 59 insertions, 6 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index 8a00245be51e..7afafb629706 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -261,6 +261,35 @@ static inline const char *iwl3945_get_tx_fail_reason(u32 status) | |||
261 | } | 261 | } |
262 | #endif | 262 | #endif |
263 | 263 | ||
264 | /* | ||
265 | * get ieee prev rate from rate scale table. | ||
266 | * for A and B mode we need to overright prev | ||
267 | * value | ||
268 | */ | ||
269 | int iwl3945_rs_next_rate(struct iwl3945_priv *priv, int rate) | ||
270 | { | ||
271 | int next_rate = iwl3945_get_prev_ieee_rate(rate); | ||
272 | |||
273 | switch (priv->band) { | ||
274 | case IEEE80211_BAND_5GHZ: | ||
275 | if (rate == IWL_RATE_12M_INDEX) | ||
276 | next_rate = IWL_RATE_9M_INDEX; | ||
277 | else if (rate == IWL_RATE_6M_INDEX) | ||
278 | next_rate = IWL_RATE_6M_INDEX; | ||
279 | break; | ||
280 | /* XXX cannot be invoked in current mac80211 so not a regression | ||
281 | case MODE_IEEE80211B: | ||
282 | if (rate == IWL_RATE_11M_INDEX_TABLE) | ||
283 | next_rate = IWL_RATE_5M_INDEX_TABLE; | ||
284 | break; | ||
285 | */ | ||
286 | default: | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | return next_rate; | ||
291 | } | ||
292 | |||
264 | 293 | ||
265 | /** | 294 | /** |
266 | * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd | 295 | * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd |
@@ -308,6 +337,7 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, | |||
308 | struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; | 337 | struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0]; |
309 | u32 status = le32_to_cpu(tx_resp->status); | 338 | u32 status = le32_to_cpu(tx_resp->status); |
310 | int rate_idx; | 339 | int rate_idx; |
340 | int fail, i; | ||
311 | 341 | ||
312 | if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { | 342 | if ((index >= txq->q.n_bd) || (iwl3945_x2_queue_used(&txq->q, index) == 0)) { |
313 | IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " | 343 | IWL_ERROR("Read index for DMA queue txq_id (%d) index %d " |
@@ -318,9 +348,36 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, | |||
318 | } | 348 | } |
319 | 349 | ||
320 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); | 350 | info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb[0]); |
321 | memset(&info->status, 0, sizeof(info->status)); | 351 | ieee80211_tx_info_clear_status(info); |
352 | |||
353 | /* Fill the MRR chain with some info about on-chip retransmissions */ | ||
354 | rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); | ||
355 | if (info->band == IEEE80211_BAND_5GHZ) | ||
356 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
357 | |||
358 | fail = tx_resp->failure_frame; | ||
359 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | ||
360 | int next = iwl3945_rs_next_rate(priv, rate_idx); | ||
361 | |||
362 | info->status.rates[i].idx = rate_idx; | ||
363 | |||
364 | /* | ||
365 | * Put remaining into the last count as best approximation | ||
366 | * of saying exactly what the hardware would have done... | ||
367 | */ | ||
368 | if ((rate_idx == next) || (i == IEEE80211_TX_MAX_RATES - 1)) { | ||
369 | info->status.rates[i].count = fail; | ||
370 | break; | ||
371 | } | ||
372 | |||
373 | info->status.rates[i].count = priv->retry_rate; | ||
374 | fail -= priv->retry_rate; | ||
375 | rate_idx = next; | ||
376 | if (fail <= 0) | ||
377 | break; | ||
378 | } | ||
379 | info->status.rates[i].count++; /* add final attempt */ | ||
322 | 380 | ||
323 | info->status.retry_count = tx_resp->failure_frame; | ||
324 | /* tx_status->rts_retry_count = tx_resp->failure_rts; */ | 381 | /* tx_status->rts_retry_count = tx_resp->failure_rts; */ |
325 | info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? | 382 | info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ? |
326 | IEEE80211_TX_STAT_ACK : 0; | 383 | IEEE80211_TX_STAT_ACK : 0; |
@@ -329,10 +386,6 @@ static void iwl3945_rx_reply_tx(struct iwl3945_priv *priv, | |||
329 | txq_id, iwl3945_get_tx_fail_reason(status), status, | 386 | txq_id, iwl3945_get_tx_fail_reason(status), status, |
330 | tx_resp->rate, tx_resp->failure_frame); | 387 | tx_resp->rate, tx_resp->failure_frame); |
331 | 388 | ||
332 | rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate); | ||
333 | if (info->band == IEEE80211_BAND_5GHZ) | ||
334 | rate_idx -= IWL_FIRST_OFDM_RATE; | ||
335 | info->tx_rate_idx = rate_idx; | ||
336 | IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); | 389 | IWL_DEBUG_TX_REPLY("Tx queue reclaim %d\n", index); |
337 | iwl3945_tx_queue_reclaim(priv, txq_id, index); | 390 | iwl3945_tx_queue_reclaim(priv, txq_id, index); |
338 | 391 | ||