aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>2008-06-30 05:23:11 -0400
committerJohn W. Linville <linville@tuxdriver.com>2008-06-30 17:37:40 -0400
commit653fa4a07525e4cd9e7b90e6fc1f792119910636 (patch)
tree8116450aaf0ed40fdbb268973996f7a06438deb9 /drivers/net
parent4b8817b2a06958efd868677880334229fe5a96cf (diff)
iwlwifi: setup compressed BA handler
This patch sets the compressed BA handler for 5000. This allows the rate scaling algorithm to take in count frames that were sent in AMPDUs. The compressed BA handler has been moved to iwl-rx.c since it is common to 4965 and 5000. Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Tomas Winkler <tomas.winkler@intel.com> Signed-off-by: Zhu Yi <yi.zhu@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-4965.c146
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c143
-rw-r--r--drivers/net/wireless/iwlwifi/iwl4965-base.c6
5 files changed, 151 insertions, 150 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c
index d8e6d2e6a86b..57a853d22115 100644
--- a/drivers/net/wireless/iwlwifi/iwl-4965.c
+++ b/drivers/net/wireless/iwlwifi/iwl-4965.c
@@ -1930,74 +1930,6 @@ static void iwl4965_temperature_calib(struct iwl_priv *priv,
1930} 1930}
1931 1931
1932/** 1932/**
1933 * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
1934 *
1935 * Go through block-ack's bitmap of ACK'd frames, update driver's record of
1936 * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
1937 */
1938static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
1939 struct iwl_ht_agg *agg,
1940 struct iwl4965_compressed_ba_resp*
1941 ba_resp)
1942
1943{
1944 int i, sh, ack;
1945 u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
1946 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
1947 u64 bitmap;
1948 int successes = 0;
1949 struct ieee80211_tx_info *info;
1950
1951 if (unlikely(!agg->wait_for_ba)) {
1952 IWL_ERROR("Received BA when not expected\n");
1953 return -EINVAL;
1954 }
1955
1956 /* Mark that the expected block-ack response arrived */
1957 agg->wait_for_ba = 0;
1958 IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
1959
1960 /* Calculate shift to align block-ack bits with our Tx window bits */
1961 sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
1962 if (sh < 0) /* tbw something is wrong with indices */
1963 sh += 0x100;
1964
1965 /* don't use 64-bit values for now */
1966 bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
1967
1968 if (agg->frame_count > (64 - sh)) {
1969 IWL_DEBUG_TX_REPLY("more frames than bitmap size");
1970 return -1;
1971 }
1972
1973 /* check for success or failure according to the
1974 * transmitted bitmap and block-ack bitmap */
1975 bitmap &= agg->bitmap;
1976
1977 /* For each frame attempted in aggregation,
1978 * update driver's record of tx frame's status. */
1979 for (i = 0; i < agg->frame_count ; i++) {
1980 ack = bitmap & (1 << i);
1981 successes += !!ack;
1982 IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
1983 ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
1984 agg->start_idx + i);
1985 }
1986
1987 info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
1988 memset(&info->status, 0, sizeof(info->status));
1989 info->flags = IEEE80211_TX_STAT_ACK;
1990 info->flags |= IEEE80211_TX_STAT_AMPDU;
1991 info->status.ampdu_ack_map = successes;
1992 info->status.ampdu_ack_len = agg->frame_count;
1993 iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
1994
1995 IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
1996
1997 return 0;
1998}
1999
2000/**
2001 * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration 1933 * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
2002 */ 1934 */
2003static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv, 1935static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
@@ -2048,82 +1980,6 @@ static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
2048 return 0; 1980 return 0;
2049} 1981}
2050 1982
2051
2052/**
2053 * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
2054 *
2055 * Handles block-acknowledge notification from device, which reports success
2056 * of frames sent via aggregation.
2057 */
2058static void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
2059 struct iwl_rx_mem_buffer *rxb)
2060{
2061 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
2062 struct iwl4965_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
2063 int index;
2064 struct iwl_tx_queue *txq = NULL;
2065 struct iwl_ht_agg *agg;
2066 DECLARE_MAC_BUF(mac);
2067
2068 /* "flow" corresponds to Tx queue */
2069 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
2070
2071 /* "ssn" is start of block-ack Tx window, corresponds to index
2072 * (in Tx queue's circular buffer) of first TFD/frame in window */
2073 u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
2074
2075 if (scd_flow >= priv->hw_params.max_txq_num) {
2076 IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
2077 return;
2078 }
2079
2080 txq = &priv->txq[scd_flow];
2081 agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
2082
2083 /* Find index just before block-ack window */
2084 index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
2085
2086 /* TODO: Need to get this copy more safely - now good for debug */
2087
2088 IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
2089 "sta_id = %d\n",
2090 agg->wait_for_ba,
2091 print_mac(mac, (u8*) &ba_resp->sta_addr_lo32),
2092 ba_resp->sta_id);
2093 IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
2094 "%d, scd_ssn = %d\n",
2095 ba_resp->tid,
2096 ba_resp->seq_ctl,
2097 (unsigned long long)le64_to_cpu(ba_resp->bitmap),
2098 ba_resp->scd_flow,
2099 ba_resp->scd_ssn);
2100 IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
2101 agg->start_idx,
2102 (unsigned long long)agg->bitmap);
2103
2104 /* Update driver's record of ACK vs. not for each frame in window */
2105 iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
2106
2107 /* Release all TFDs before the SSN, i.e. all TFDs in front of
2108 * block-ack window (we assume that they've been successfully
2109 * transmitted ... if not, it's too late anyway). */
2110 if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
2111 /* calculate mac80211 ampdu sw queue to wake */
2112 int ampdu_q =
2113 scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues;
2114 int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
2115 priv->stations[ba_resp->sta_id].
2116 tid[ba_resp->tid].tfds_in_queue -= freed;
2117 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
2118 priv->mac80211_registered &&
2119 agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
2120 ieee80211_wake_queue(priv->hw, ampdu_q);
2121
2122 iwl_txq_check_empty(priv, ba_resp->sta_id,
2123 ba_resp->tid, scd_flow);
2124 }
2125}
2126
2127/** 1983/**
2128 * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue 1984 * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
2129 */ 1985 */
@@ -2555,8 +2411,6 @@ static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
2555 priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx; 2411 priv->rx_handlers[REPLY_RX] = iwl_rx_reply_rx;
2556 /* Tx response */ 2412 /* Tx response */
2557 priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx; 2413 priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
2558 /* block ack */
2559 priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
2560} 2414}
2561 2415
2562static void iwl4965_setup_deferred_work(struct iwl_priv *priv) 2416static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 9f8446c5a1bc..fe05d60ebe63 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -1536,7 +1536,7 @@ struct iwl5000_tx_resp {
1536 * 1536 *
1537 * Reports Block-Acknowledge from recipient station 1537 * Reports Block-Acknowledge from recipient station
1538 */ 1538 */
1539struct iwl4965_compressed_ba_resp { 1539struct iwl_compressed_ba_resp {
1540 __le32 sta_addr_lo32; 1540 __le32 sta_addr_lo32;
1541 __le16 sta_addr_hi16; 1541 __le16 sta_addr_hi16;
1542 __le16 reserved; 1542 __le16 reserved;
@@ -3001,7 +3001,7 @@ struct iwl_rx_packet {
3001 struct iwl4965_sleep_notification sleep_notif; 3001 struct iwl4965_sleep_notification sleep_notif;
3002 struct iwl4965_spectrum_resp spectrum; 3002 struct iwl4965_spectrum_resp spectrum;
3003 struct iwl_notif_statistics stats; 3003 struct iwl_notif_statistics stats;
3004 struct iwl4965_compressed_ba_resp compressed_ba; 3004 struct iwl_compressed_ba_resp compressed_ba;
3005 struct iwl4965_missed_beacon_notif missed_beacon; 3005 struct iwl4965_missed_beacon_notif missed_beacon;
3006 struct iwl5000_calibration calib; 3006 struct iwl5000_calibration calib;
3007 __le32 status; 3007 __le32 status;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 0d8cc8c659a0..06c272cee97d 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -377,6 +377,8 @@ extern void iwl_rx_reply_rx(struct iwl_priv *priv,
377 struct iwl_rx_mem_buffer *rxb); 377 struct iwl_rx_mem_buffer *rxb);
378extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv, 378extern void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
379 struct iwl_rx_mem_buffer *rxb); 379 struct iwl_rx_mem_buffer *rxb);
380void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
381 struct iwl_rx_mem_buffer *rxb);
380 382
381static inline int iwl_send_rxon_assoc(struct iwl_priv *priv) 383static inline int iwl_send_rxon_assoc(struct iwl_priv *priv)
382{ 384{
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 7296e2846ec3..032641d4c7d1 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -1350,6 +1350,149 @@ int iwl_txq_check_empty(struct iwl_priv *priv, int sta_id, u8 tid, int txq_id)
1350} 1350}
1351EXPORT_SYMBOL(iwl_txq_check_empty); 1351EXPORT_SYMBOL(iwl_txq_check_empty);
1352 1352
1353/**
1354 * iwl_tx_status_reply_compressed_ba - Update tx status from block-ack
1355 *
1356 * Go through block-ack's bitmap of ACK'd frames, update driver's record of
1357 * ACK vs. not. This gets sent to mac80211, then to rate scaling algo.
1358 */
1359static int iwl_tx_status_reply_compressed_ba(struct iwl_priv *priv,
1360 struct iwl_ht_agg *agg,
1361 struct iwl_compressed_ba_resp *ba_resp)
1362
1363{
1364 int i, sh, ack;
1365 u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
1366 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
1367 u64 bitmap;
1368 int successes = 0;
1369 struct ieee80211_tx_info *info;
1370
1371 if (unlikely(!agg->wait_for_ba)) {
1372 IWL_ERROR("Received BA when not expected\n");
1373 return -EINVAL;
1374 }
1375
1376 /* Mark that the expected block-ack response arrived */
1377 agg->wait_for_ba = 0;
1378 IWL_DEBUG_TX_REPLY("BA %d %d\n", agg->start_idx, ba_resp->seq_ctl);
1379
1380 /* Calculate shift to align block-ack bits with our Tx window bits */
1381 sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl>>4);
1382 if (sh < 0) /* tbw something is wrong with indices */
1383 sh += 0x100;
1384
1385 /* don't use 64-bit values for now */
1386 bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
1387
1388 if (agg->frame_count > (64 - sh)) {
1389 IWL_DEBUG_TX_REPLY("more frames than bitmap size");
1390 return -1;
1391 }
1392
1393 /* check for success or failure according to the
1394 * transmitted bitmap and block-ack bitmap */
1395 bitmap &= agg->bitmap;
1396
1397 /* For each frame attempted in aggregation,
1398 * update driver's record of tx frame's status. */
1399 for (i = 0; i < agg->frame_count ; i++) {
1400 ack = bitmap & (1 << i);
1401 successes += !!ack;
1402 IWL_DEBUG_TX_REPLY("%s ON i=%d idx=%d raw=%d\n",
1403 ack? "ACK":"NACK", i, (agg->start_idx + i) & 0xff,
1404 agg->start_idx + i);
1405 }
1406
1407 info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb[0]);
1408 memset(&info->status, 0, sizeof(info->status));
1409 info->flags = IEEE80211_TX_STAT_ACK;
1410 info->flags |= IEEE80211_TX_STAT_AMPDU;
1411 info->status.ampdu_ack_map = successes;
1412 info->status.ampdu_ack_len = agg->frame_count;
1413 iwl_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
1414
1415 IWL_DEBUG_TX_REPLY("Bitmap %llx\n", (unsigned long long)bitmap);
1416
1417 return 0;
1418}
1419
1420/**
1421 * iwl_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
1422 *
1423 * Handles block-acknowledge notification from device, which reports success
1424 * of frames sent via aggregation.
1425 */
1426void iwl_rx_reply_compressed_ba(struct iwl_priv *priv,
1427 struct iwl_rx_mem_buffer *rxb)
1428{
1429 struct iwl_rx_packet *pkt = (struct iwl_rx_packet *)rxb->skb->data;
1430 struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
1431 int index;
1432 struct iwl_tx_queue *txq = NULL;
1433 struct iwl_ht_agg *agg;
1434 DECLARE_MAC_BUF(mac);
1435
1436 /* "flow" corresponds to Tx queue */
1437 u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
1438
1439 /* "ssn" is start of block-ack Tx window, corresponds to index
1440 * (in Tx queue's circular buffer) of first TFD/frame in window */
1441 u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
1442
1443 if (scd_flow >= priv->hw_params.max_txq_num) {
1444 IWL_ERROR("BUG_ON scd_flow is bigger than number of queues");
1445 return;
1446 }
1447
1448 txq = &priv->txq[scd_flow];
1449 agg = &priv->stations[ba_resp->sta_id].tid[ba_resp->tid].agg;
1450
1451 /* Find index just before block-ack window */
1452 index = iwl_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
1453
1454 /* TODO: Need to get this copy more safely - now good for debug */
1455
1456 IWL_DEBUG_TX_REPLY("REPLY_COMPRESSED_BA [%d]Received from %s, "
1457 "sta_id = %d\n",
1458 agg->wait_for_ba,
1459 print_mac(mac, (u8 *) &ba_resp->sta_addr_lo32),
1460 ba_resp->sta_id);
1461 IWL_DEBUG_TX_REPLY("TID = %d, SeqCtl = %d, bitmap = 0x%llx, scd_flow = "
1462 "%d, scd_ssn = %d\n",
1463 ba_resp->tid,
1464 ba_resp->seq_ctl,
1465 (unsigned long long)le64_to_cpu(ba_resp->bitmap),
1466 ba_resp->scd_flow,
1467 ba_resp->scd_ssn);
1468 IWL_DEBUG_TX_REPLY("DAT start_idx = %d, bitmap = 0x%llx \n",
1469 agg->start_idx,
1470 (unsigned long long)agg->bitmap);
1471
1472 /* Update driver's record of ACK vs. not for each frame in window */
1473 iwl_tx_status_reply_compressed_ba(priv, agg, ba_resp);
1474
1475 /* Release all TFDs before the SSN, i.e. all TFDs in front of
1476 * block-ack window (we assume that they've been successfully
1477 * transmitted ... if not, it's too late anyway). */
1478 if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
1479 /* calculate mac80211 ampdu sw queue to wake */
1480 int ampdu_q =
1481 scd_flow - priv->hw_params.first_ampdu_q + priv->hw->queues;
1482 int freed = iwl_tx_queue_reclaim(priv, scd_flow, index);
1483 priv->stations[ba_resp->sta_id].
1484 tid[ba_resp->tid].tfds_in_queue -= freed;
1485 if (iwl_queue_space(&txq->q) > txq->q.low_mark &&
1486 priv->mac80211_registered &&
1487 agg->state != IWL_EMPTYING_HW_QUEUE_DELBA)
1488 ieee80211_wake_queue(priv->hw, ampdu_q);
1489
1490 iwl_txq_check_empty(priv, ba_resp->sta_id,
1491 ba_resp->tid, scd_flow);
1492 }
1493}
1494EXPORT_SYMBOL(iwl_rx_reply_compressed_ba);
1495
1353#ifdef CONFIG_IWLWIF_DEBUG 1496#ifdef CONFIG_IWLWIF_DEBUG
1354#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x 1497#define TX_STATUS_ENTRY(x) case TX_STATUS_FAIL_ ## x: return #x
1355 1498
diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c
index 4129e90f360a..a87e870f96d0 100644
--- a/drivers/net/wireless/iwlwifi/iwl4965-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c
@@ -1249,7 +1249,7 @@ static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
1249 * This function chains into the hardware specific files for them to setup 1249 * This function chains into the hardware specific files for them to setup
1250 * any hardware specific handlers as well. 1250 * any hardware specific handlers as well.
1251 */ 1251 */
1252static void iwl4965_setup_rx_handlers(struct iwl_priv *priv) 1252static void iwl_setup_rx_handlers(struct iwl_priv *priv)
1253{ 1253{
1254 priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive; 1254 priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
1255 priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error; 1255 priv->rx_handlers[REPLY_ERROR] = iwl4965_rx_reply_error;
@@ -1279,6 +1279,8 @@ static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
1279 /* Rx handlers */ 1279 /* Rx handlers */
1280 priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy; 1280 priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl_rx_reply_rx_phy;
1281 priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx; 1281 priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl_rx_reply_rx;
1282 /* block ack */
1283 priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl_rx_reply_compressed_ba;
1282 /* Set up hardware specific Rx handlers */ 1284 /* Set up hardware specific Rx handlers */
1283 priv->cfg->ops->lib->rx_handler_setup(priv); 1285 priv->cfg->ops->lib->rx_handler_setup(priv);
1284} 1286}
@@ -4272,7 +4274,7 @@ static int iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *e
4272 4274
4273 4275
4274 iwl_setup_deferred_work(priv); 4276 iwl_setup_deferred_work(priv);
4275 iwl4965_setup_rx_handlers(priv); 4277 iwl_setup_rx_handlers(priv);
4276 4278
4277 /******************** 4279 /********************
4278 * 9. Conclude 4280 * 9. Conclude