diff options
author | David S. Miller <davem@davemloft.net> | 2010-04-07 19:41:03 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2010-04-07 19:41:03 -0400 |
commit | 005c93b5d876edf670b4c71d8dd79dc4e845a099 (patch) | |
tree | 5ee50d6174e3ed9f4fec8fec9ca53e780b874a23 /drivers/net | |
parent | fb9e2d887243499b8d28efcf80821c4f6a092395 (diff) | |
parent | 1144601118507f8b3b676a9a392584d216d3f2cc (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.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-rs.c | 55 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 107 |
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 | */ | ||
352 | static 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 | */ |
355 | static int rs_collect_tx_data(struct iwl_rate_scale_data *windows, | 366 | static 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 | */ | ||
745 | static 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 | ******************************************************/ |
445 | int iwl_txq_ctx_reset(struct iwl_priv *priv); | 445 | int iwl_txq_ctx_alloc(struct iwl_priv *priv); |
446 | void iwl_txq_ctx_reset(struct iwl_priv *priv); | ||
446 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 447 | void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
447 | int iwl_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv, | 448 | int 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, | |||
456 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); | 457 | void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq); |
457 | int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 458 | int 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); |
460 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
461 | int slots_num, u32 txq_id); | ||
459 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 462 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
460 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); | 463 | int iwl_tx_agg_start(struct iwl_priv *priv, const u8 *ra, u16 tid, u16 *ssn); |
461 | int iwl_tx_agg_stop(struct iwl_priv *priv , const u8 *ra, u16 tid); | 464 | int 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 | } |
410 | EXPORT_SYMBOL(iwl_tx_queue_init); | 434 | EXPORT_SYMBOL(iwl_tx_queue_init); |
411 | 435 | ||
436 | void 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 | } | ||
454 | EXPORT_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) | |||
437 | EXPORT_SYMBOL(iwl_hw_txq_ctx_free); | 480 | EXPORT_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 | */ |
446 | int iwl_txq_ctx_reset(struct iwl_priv *priv) | 489 | int 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 | ||
549 | void 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 | */ |
509 | void iwl_txq_ctx_stop(struct iwl_priv *priv) | 575 | void 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 | } |
531 | EXPORT_SYMBOL(iwl_txq_ctx_stop); | 594 | EXPORT_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 | } |
1267 | EXPORT_SYMBOL(iwl_tx_cmd_complete); | 1348 | EXPORT_SYMBOL(iwl_tx_cmd_complete); |
1268 | 1349 | ||