diff options
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-lib.c | 11 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 39 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 20 |
4 files changed, 58 insertions, 15 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c index 384b45c519f1..c465c8590833 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c | |||
@@ -512,10 +512,13 @@ int iwlagn_hw_nic_init(struct iwl_priv *priv) | |||
512 | 512 | ||
513 | spin_unlock_irqrestore(&priv->lock, flags); | 513 | spin_unlock_irqrestore(&priv->lock, flags); |
514 | 514 | ||
515 | /* Allocate and init all Tx and Command queues */ | 515 | /* Allocate or reset and init all Tx and Command queues */ |
516 | ret = iwlagn_txq_ctx_reset(priv); | 516 | if (!priv->txq) { |
517 | if (ret) | 517 | ret = iwlagn_txq_ctx_alloc(priv); |
518 | return ret; | 518 | if (ret) |
519 | return ret; | ||
520 | } else | ||
521 | iwlagn_txq_ctx_reset(priv); | ||
519 | 522 | ||
520 | set_bit(STATUS_INIT, &priv->status); | 523 | set_bit(STATUS_INIT, &priv->status); |
521 | 524 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index a76e14351b5a..3077eac58880 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -809,8 +809,7 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | |||
809 | 809 | ||
810 | /* Tx queues */ | 810 | /* Tx queues */ |
811 | if (priv->txq) { | 811 | if (priv->txq) { |
812 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; | 812 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) |
813 | txq_id++) | ||
814 | if (txq_id == IWL_CMD_QUEUE_NUM) | 813 | if (txq_id == IWL_CMD_QUEUE_NUM) |
815 | iwl_cmd_queue_free(priv); | 814 | iwl_cmd_queue_free(priv); |
816 | else | 815 | else |
@@ -825,15 +824,15 @@ void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv) | |||
825 | } | 824 | } |
826 | 825 | ||
827 | /** | 826 | /** |
828 | * iwlagn_txq_ctx_reset - Reset TX queue context | 827 | * iwlagn_txq_ctx_alloc - allocate TX queue context |
829 | * Destroys all DMA structures and initialize them again | 828 | * Allocate all Tx DMA structures and initialize them |
830 | * | 829 | * |
831 | * @param priv | 830 | * @param priv |
832 | * @return error code | 831 | * @return error code |
833 | */ | 832 | */ |
834 | int iwlagn_txq_ctx_reset(struct iwl_priv *priv) | 833 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv) |
835 | { | 834 | { |
836 | int ret = 0; | 835 | int ret; |
837 | int txq_id, slots_num; | 836 | int txq_id, slots_num; |
838 | unsigned long flags; | 837 | unsigned long flags; |
839 | 838 | ||
@@ -891,8 +890,31 @@ int iwlagn_txq_ctx_reset(struct iwl_priv *priv) | |||
891 | return ret; | 890 | return ret; |
892 | } | 891 | } |
893 | 892 | ||
893 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | ||
894 | { | ||
895 | int txq_id, slots_num; | ||
896 | unsigned long flags; | ||
897 | |||
898 | spin_lock_irqsave(&priv->lock, flags); | ||
899 | |||
900 | /* Turn off all Tx DMA fifos */ | ||
901 | priv->cfg->ops->lib->txq_set_sched(priv, 0); | ||
902 | |||
903 | /* Tell NIC where to find the "keep warm" buffer */ | ||
904 | iwl_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4); | ||
905 | |||
906 | spin_unlock_irqrestore(&priv->lock, flags); | ||
907 | |||
908 | /* Alloc and init all Tx queues, including the command queue (#4) */ | ||
909 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) { | ||
910 | slots_num = txq_id == IWL_CMD_QUEUE_NUM ? | ||
911 | TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS; | ||
912 | iwl_tx_queue_reset(priv, &priv->txq[txq_id], slots_num, txq_id); | ||
913 | } | ||
914 | } | ||
915 | |||
894 | /** | 916 | /** |
895 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels, free Tx queue memory | 917 | * iwlagn_txq_ctx_stop - Stop all Tx DMA channels |
896 | */ | 918 | */ |
897 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | 919 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) |
898 | { | 920 | { |
@@ -912,9 +934,6 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | |||
912 | 1000); | 934 | 1000); |
913 | } | 935 | } |
914 | spin_unlock_irqrestore(&priv->lock, flags); | 936 | spin_unlock_irqrestore(&priv->lock, flags); |
915 | |||
916 | /* Deallocate memory for all Tx queues */ | ||
917 | iwlagn_hw_txq_ctx_free(priv); | ||
918 | } | 937 | } |
919 | 938 | ||
920 | /* | 939 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h index 608060abe80c..5d3142287e14 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.h +++ b/drivers/net/wireless/iwlwifi/iwl-agn.h | |||
@@ -145,7 +145,8 @@ void iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, | |||
145 | struct iwl_rx_mem_buffer *rxb); | 145 | struct iwl_rx_mem_buffer *rxb); |
146 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); | 146 | int iwlagn_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index); |
147 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); | 147 | void iwlagn_hw_txq_ctx_free(struct iwl_priv *priv); |
148 | int iwlagn_txq_ctx_reset(struct iwl_priv *priv); | 148 | int iwlagn_txq_ctx_alloc(struct iwl_priv *priv); |
149 | void iwlagn_txq_ctx_reset(struct iwl_priv *priv); | ||
149 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); | 150 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv); |
150 | 151 | ||
151 | static inline u32 iwl_tx_status_to_mac80211(u32 status) | 152 | static inline u32 iwl_tx_status_to_mac80211(u32 status) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index aea6a2eee9c3..c3c6505a8c69 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -394,6 +394,26 @@ out_free_arrays: | |||
394 | } | 394 | } |
395 | EXPORT_SYMBOL(iwl_tx_queue_init); | 395 | EXPORT_SYMBOL(iwl_tx_queue_init); |
396 | 396 | ||
397 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | ||
398 | int slots_num, u32 txq_id) | ||
399 | { | ||
400 | int actual_slots = slots_num; | ||
401 | |||
402 | if (txq_id == IWL_CMD_QUEUE_NUM) | ||
403 | actual_slots++; | ||
404 | |||
405 | memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots); | ||
406 | |||
407 | txq->need_update = 0; | ||
408 | |||
409 | /* Initialize queue's high/low-water marks, and head/tail indexes */ | ||
410 | iwl_queue_init(priv, &txq->q, TFD_QUEUE_SIZE_MAX, slots_num, txq_id); | ||
411 | |||
412 | /* Tell device where to find queue */ | ||
413 | priv->cfg->ops->lib->txq_init(priv, txq); | ||
414 | } | ||
415 | EXPORT_SYMBOL(iwl_tx_queue_reset); | ||
416 | |||
397 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ | 417 | /*************** HOST COMMAND QUEUE FUNCTIONS *****/ |
398 | 418 | ||
399 | /** | 419 | /** |