aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-04-07 19:41:03 -0400
committerDavid S. Miller <davem@davemloft.net>2010-04-07 19:41:03 -0400
commit005c93b5d876edf670b4c71d8dd79dc4e845a099 (patch)
tree5ee50d6174e3ed9f4fec8fec9ca53e780b874a23 /drivers/net
parentfb9e2d887243499b8d28efcf80821c4f6a092395 (diff)
parent1144601118507f8b3b676a9a392584d216d3f2cc (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-2.6
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c55
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-tx.c107
5 files changed, 130 insertions, 51 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 67ca4e5a6017..115e1aeedb59 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1532,8 +1532,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
1532 all_wiphys_idle = ath9k_all_wiphys_idle(sc); 1532 all_wiphys_idle = ath9k_all_wiphys_idle(sc);
1533 ath9k_set_wiphy_idle(aphy, idle); 1533 ath9k_set_wiphy_idle(aphy, idle);
1534 1534
1535 if (!idle && all_wiphys_idle) 1535 enable_radio = (!idle && all_wiphys_idle);
1536 enable_radio = true;
1537 1536
1538 /* 1537 /*
1539 * After we unlock here its possible another wiphy 1538 * After we unlock here its possible another wiphy
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 8bf7c20b9d39..be00cb3b1d0e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -345,6 +345,17 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
345 !!(rate_n_flags & RATE_MCS_ANT_C_MSK); 345 !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
346} 346}
347 347
348/*
349 * Static function to get the expected throughput from an iwl_scale_tbl_info
350 * that wraps a NULL pointer check
351 */
352static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
353{
354 if (tbl->expected_tpt)
355 return tbl->expected_tpt[rs_index];
356 return 0;
357}
358
348/** 359/**
349 * rs_collect_tx_data - Update the success/failure sliding window 360 * rs_collect_tx_data - Update the success/failure sliding window
350 * 361 *
@@ -352,19 +363,21 @@ static inline int get_num_of_ant_from_rate(u32 rate_n_flags)
352 * at this rate. window->data contains the bitmask of successful 363 * at this rate. window->data contains the bitmask of successful
353 * packets. 364 * packets.
354 */ 365 */
355static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, 366static int rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
356 int scale_index, s32 tpt, int attempts, 367 int scale_index, int attempts, int successes)
357 int successes)
358{ 368{
359 struct iwl_rate_scale_data *window = NULL; 369 struct iwl_rate_scale_data *window = NULL;
360 static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1)); 370 static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
361 s32 fail_count; 371 s32 fail_count, tpt;
362 372
363 if (scale_index < 0 || scale_index >= IWL_RATE_COUNT) 373 if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
364 return -EINVAL; 374 return -EINVAL;
365 375
366 /* Select window for current tx bit rate */ 376 /* Select window for current tx bit rate */
367 window = &(windows[scale_index]); 377 window = &(tbl->win[scale_index]);
378
379 /* Get expected throughput */
380 tpt = get_expected_tpt(tbl, scale_index);
368 381
369 /* 382 /*
370 * Keep track of only the latest 62 tx frame attempts in this rate's 383 * Keep track of only the latest 62 tx frame attempts in this rate's
@@ -738,16 +751,6 @@ static bool table_type_matches(struct iwl_scale_tbl_info *a,
738 return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) && 751 return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
739 (a->is_SGI == b->is_SGI); 752 (a->is_SGI == b->is_SGI);
740} 753}
741/*
742 * Static function to get the expected throughput from an iwl_scale_tbl_info
743 * that wraps a NULL pointer check
744 */
745static s32 get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
746{
747 if (tbl->expected_tpt)
748 return tbl->expected_tpt[rs_index];
749 return 0;
750}
751 754
752/* 755/*
753 * mac80211 sends us Tx status 756 * mac80211 sends us Tx status
@@ -764,12 +767,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
764 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 767 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
765 struct iwl_priv *priv = (struct iwl_priv *)priv_r; 768 struct iwl_priv *priv = (struct iwl_priv *)priv_r;
766 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 769 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
767 struct iwl_rate_scale_data *window = NULL;
768 enum mac80211_rate_control_flags mac_flags; 770 enum mac80211_rate_control_flags mac_flags;
769 u32 tx_rate; 771 u32 tx_rate;
770 struct iwl_scale_tbl_info tbl_type; 772 struct iwl_scale_tbl_info tbl_type;
771 struct iwl_scale_tbl_info *curr_tbl, *other_tbl; 773 struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
772 s32 tpt = 0;
773 774
774 IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n"); 775 IWL_DEBUG_RATE_LIMIT(priv, "get frame ack response, update rate scale window\n");
775 776
@@ -852,7 +853,6 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
852 IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n"); 853 IWL_DEBUG_RATE(priv, "Neither active nor search matches tx rate\n");
853 return; 854 return;
854 } 855 }
855 window = (struct iwl_rate_scale_data *)&(curr_tbl->win[0]);
856 856
857 /* 857 /*
858 * Updating the frame history depends on whether packets were 858 * Updating the frame history depends on whether packets were
@@ -865,8 +865,7 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
865 tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags); 865 tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
866 rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type, 866 rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
867 &rs_index); 867 &rs_index);
868 tpt = get_expected_tpt(curr_tbl, rs_index); 868 rs_collect_tx_data(curr_tbl, rs_index,
869 rs_collect_tx_data(window, rs_index, tpt,
870 info->status.ampdu_ack_len, 869 info->status.ampdu_ack_len,
871 info->status.ampdu_ack_map); 870 info->status.ampdu_ack_map);
872 871
@@ -896,19 +895,13 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
896 * table as active/search. 895 * table as active/search.
897 */ 896 */
898 if (table_type_matches(&tbl_type, curr_tbl)) 897 if (table_type_matches(&tbl_type, curr_tbl))
899 tpt = get_expected_tpt(curr_tbl, rs_index); 898 tmp_tbl = curr_tbl;
900 else if (table_type_matches(&tbl_type, other_tbl)) 899 else if (table_type_matches(&tbl_type, other_tbl))
901 tpt = get_expected_tpt(other_tbl, rs_index); 900 tmp_tbl = other_tbl;
902 else 901 else
903 continue; 902 continue;
904 903 rs_collect_tx_data(tmp_tbl, rs_index, 1,
905 /* Constants mean 1 transmission, 0 successes */ 904 i < retries ? 0 : legacy_success);
906 if (i < retries)
907 rs_collect_tx_data(window, rs_index, tpt, 1,
908 0);
909 else
910 rs_collect_tx_data(window, rs_index, tpt, 1,
911 legacy_success);
912 } 905 }
913 906
914 /* Update success/fail counts if not searching for new mode */ 907 /* Update success/fail counts if not searching for new mode */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 112149e9b31e..894bcb8b8b37 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -307,10 +307,13 @@ int iwl_hw_nic_init(struct iwl_priv *priv)
307 307
308 spin_unlock_irqrestore(&priv->lock, flags); 308 spin_unlock_irqrestore(&priv->lock, flags);
309 309
310 /* Allocate and init all Tx and Command queues */ 310 /* Allocate or reset and init all Tx and Command queues */
311 ret = iwl_txq_ctx_reset(priv); 311 if (!priv->txq) {
312 if (ret) 312 ret = iwl_txq_ctx_alloc(priv);
313 return ret; 313 if (ret)
314 return ret;
315 } else
316 iwl_txq_ctx_reset(priv);
314 317
315 set_bit(STATUS_INIT, &priv->status); 318 set_bit(STATUS_INIT, &priv->status);
316 319
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 4ef7739f9e8e..732590f5fe30 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -442,7 +442,8 @@ void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
442/***************************************************** 442/*****************************************************
443* TX 443* TX
444******************************************************/ 444******************************************************/
445int iwl_txq_ctx_reset(struct iwl_priv *priv); 445int iwl_txq_ctx_alloc(struct iwl_priv *priv);
446void iwl_txq_ctx_reset(struct iwl_priv *priv);
446void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); 447void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
447int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, 448int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
448 struct iwl_tx_queue *txq, 449 struct iwl_tx_queue *txq,
@@ -456,6 +457,8 @@ void iwl_free_tfds_in_queue(struct iwl_priv *priv,
456void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); 457void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq);
457int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, 458int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
458 int slots_num, u32 txq_id); 459 int slots_num, u32 txq_id);
460void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
461 int slots_num, u32 txq_id);
459void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); 462void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
460int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); 463int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn);
461int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); 464int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid);
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c
index 8c12311dbb0a..343d81ad2653 100644
--- a/drivers/net/wireless/iwlwifi/iwl-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-tx.c
@@ -193,10 +193,34 @@ void iwl_cmd_queue_free(struct iwl_priv *priv)
193 struct iwl_queue *q = &txq->q; 193 struct iwl_queue *q = &txq->q;
194 struct device *dev = &priv->pci_dev->dev; 194 struct device *dev = &priv->pci_dev->dev;
195 int i; 195 int i;
196 bool huge = false;
196 197
197 if (q->n_bd == 0) 198 if (q->n_bd == 0)
198 return; 199 return;
199 200
201 for (; q->read_ptr != q->write_ptr;
202 q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
203 /* we have no way to tell if it is a huge cmd ATM */
204 i = get_cmd_index(q, q->read_ptr, 0);
205
206 if (txq->meta[i].flags & CMD_SIZE_HUGE) {
207 huge = true;
208 continue;
209 }
210
211 pci_unmap_single(priv->pci_dev,
212 pci_unmap_addr(&txq->meta[i], mapping),
213 pci_unmap_len(&txq->meta[i], len),
214 PCI_DMA_BIDIRECTIONAL);
215 }
216 if (huge) {
217 i = q->n_window;
218 pci_unmap_single(priv->pci_dev,
219 pci_unmap_addr(&txq->meta[i], mapping),
220 pci_unmap_len(&txq->meta[i], len),
221 PCI_DMA_BIDIRECTIONAL);
222 }
223
200 /* De-alloc array of command/tx buffers */ 224 /* De-alloc array of command/tx buffers */
201 for (i = 0; i <= TFD_CMD_SLOTS; i++) 225 for (i = 0; i <= TFD_CMD_SLOTS; i++)
202 kfree(txq->cmd[i]); 226 kfree(txq->cmd[i]);
@@ -409,6 +433,26 @@ out_free_arrays:
409} 433}
410EXPORT_SYMBOL(iwl_tx_queue_init); 434EXPORT_SYMBOL(iwl_tx_queue_init);
411 435
436void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
437 int slots_num, u32 txq_id)
438{
439 int actual_slots = slots_num;
440
441 if (txq_id == IWL_CMD_QUEUE_NUM)
442 actual_slots++;
443
444 memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
445
446 txq->need_update = 0;
447
448 /* Initialize queue's high/low-water marks, and head/tail indexes */
449 iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
450
451 /* Tell device where to find queue */
452 priv->cfg->ops->lib->txq_init(priv, txq);
453}
454EXPORT_SYMBOL(iwl_tx_queue_reset);
455
412/** 456/**
413 * iwl_hw_txq_ctx_free - Free TXQ Context 457 * iwl_hw_txq_ctx_free - Free TXQ Context
414 * 458 *
@@ -420,8 +464,7 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
420 464
421 /* Tx queues */ 465 /* Tx queues */
422 if (priv->txq) { 466 if (priv->txq) {
423 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; 467 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
424 txq_id++)
425 if (txq_id == IWL_CMD_QUEUE_NUM) 468 if (txq_id == IWL_CMD_QUEUE_NUM)
426 iwl_cmd_queue_free(priv); 469 iwl_cmd_queue_free(priv);
427 else 470 else
@@ -437,15 +480,15 @@ void iwl_hw_txq_ctx_free(struct iwl_priv *priv)
437EXPORT_SYMBOL(iwl_hw_txq_ctx_free); 480EXPORT_SYMBOL(iwl_hw_txq_ctx_free);
438 481
439/** 482/**
440 * iwl_txq_ctx_reset - Reset TX queue context 483 * iwl_txq_ctx_alloc - allocate TX queue context
441 * Destroys all DMA structures and initialize them again 484 * Allocate all Tx DMA structures and initialize them
442 * 485 *
443 * @param priv 486 * @param priv
444 * @return error code 487 * @return error code
445 */ 488 */
446int iwl_txq_ctx_reset(struct iwl_priv *priv) 489int iwl_txq_ctx_alloc(struct iwl_priv *priv)
447{ 490{
448 int ret = 0; 491 int ret;
449 int txq_id, slots_num; 492 int txq_id, slots_num;
450 unsigned long flags; 493 unsigned long flags;
451 494
@@ -503,8 +546,31 @@ int iwl_txq_ctx_reset(struct iwl_priv *priv)
503 return ret; 546 return ret;
504} 547}
505 548
549void iwl_txq_ctx_reset(struct iwl_priv *priv)
550{
551 int txq_id, slots_num;
552 unsigned long flags;
553
554 spin_lock_irqsave(&priv->lock, flags);
555
556 /* Turn off all Tx DMA fifos */
557 priv->cfg->ops->lib->txq_set_sched(priv, 0);
558
559 /* Tell NIC where to find the "keep warm" buffer */
560 iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
561
562 spin_unlock_irqrestore(&priv->lock, flags);
563
564 /* Alloc and init all Tx queues, including the command queue (#4) */
565 for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
566 slots_num = txq_id == IWL_CMD_QUEUE_NUM ?
567 TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
568 iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id);
569 }
570}
571
506/** 572/**
507 * iwl_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory 573 * iwl_txq_ctx_stop - Stop all Tx DMA channels
508 */ 574 */
509void iwl_txq_ctx_stop(struct iwl_priv *priv) 575void iwl_txq_ctx_stop(struct iwl_priv *priv)
510{ 576{
@@ -524,9 +590,6 @@ void iwl_txq_ctx_stop(struct iwl_priv *priv)
524 1000); 590 1000);
525 } 591 }
526 spin_unlock_irqrestore(&priv->lock, flags); 592 spin_unlock_irqrestore(&priv->lock, flags);
527
528 /* Deallocate memory for all Tx queues */
529 iwl_hw_txq_ctx_free(priv);
530} 593}
531EXPORT_SYMBOL(iwl_txq_ctx_stop); 594EXPORT_SYMBOL(iwl_txq_ctx_stop);
532 595
@@ -1049,6 +1112,14 @@ int iwl_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
1049 1112
1050 spin_lock_irqsave(&priv->hcmd_lock, flags); 1113 spin_lock_irqsave(&priv->hcmd_lock, flags);
1051 1114
1115 /* If this is a huge cmd, mark the huge flag also on the meta.flags
1116 * of the _original_ cmd. This is used for DMA mapping clean up.
1117 */
1118 if (cmd->flags & CMD_SIZE_HUGE) {
1119 idx = get_cmd_index(q, q->write_ptr, 0);
1120 txq->meta[idx].flags = CMD_SIZE_HUGE;
1121 }
1122
1052 idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE); 1123 idx = get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
1053 out_cmd = txq->cmd[idx]; 1124 out_cmd = txq->cmd[idx];
1054 out_meta = &txq->meta[idx]; 1125 out_meta = &txq->meta[idx];
@@ -1226,6 +1297,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1226 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME); 1297 bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
1227 struct iwl_device_cmd *cmd; 1298 struct iwl_device_cmd *cmd;
1228 struct iwl_cmd_meta *meta; 1299 struct iwl_cmd_meta *meta;
1300 struct iwl_tx_queue *txq = &priv->txq[IWL_CMD_QUEUE_NUM];
1229 1301
1230 /* If a Tx command is being handled and it isn't in the actual 1302 /* If a Tx command is being handled and it isn't in the actual
1231 * command queue then there a command routing bug has been introduced 1303 * command queue then there a command routing bug has been introduced
@@ -1239,9 +1311,17 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1239 return; 1311 return;
1240 } 1312 }
1241 1313
1242 cmd_index = get_cmd_index(&priv->txq[IWL_CMD_QUEUE_NUM].q, index, huge); 1314 /* If this is a huge cmd, clear the huge flag on the meta.flags
1243 cmd = priv->txq[IWL_CMD_QUEUE_NUM].cmd[cmd_index]; 1315 * of the _original_ cmd. So that iwl_cmd_queue_free won't unmap
1244 meta = &priv->txq[IWL_CMD_QUEUE_NUM].meta[cmd_index]; 1316 * the DMA buffer for the scan (huge) command.
1317 */
1318 if (huge) {
1319 cmd_index = get_cmd_index(&txq->q, index, 0);
1320 txq->meta[cmd_index].flags = 0;
1321 }
1322 cmd_index = get_cmd_index(&txq->q, index, huge);
1323 cmd = txq->cmd[cmd_index];
1324 meta = &txq->meta[cmd_index];
1245 1325
1246 pci_unmap_single(priv->pci_dev, 1326 pci_unmap_single(priv->pci_dev,
1247 pci_unmap_addr(meta, mapping), 1327 pci_unmap_addr(meta, mapping),
@@ -1263,6 +1343,7 @@ void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
1263 get_cmd_string(cmd->hdr.cmd)); 1343 get_cmd_string(cmd->hdr.cmd));
1264 wake_up_interruptible(&priv->wait_command_queue); 1344 wake_up_interruptible(&priv->wait_command_queue);
1265 } 1345 }
1346 meta->flags = 0;
1266} 1347}
1267EXPORT_SYMBOL(iwl_tx_cmd_complete); 1348EXPORT_SYMBOL(iwl_tx_cmd_complete);
1268 1349