diff options
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 12 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-tx.c | 71 |
3 files changed, 59 insertions, 26 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index 266490d8a39..a709d05c586 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c | |||
@@ -947,7 +947,7 @@ void iwlagn_txq_ctx_reset(struct iwl_priv *priv) | |||
947 | */ | 947 | */ |
948 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | 948 | void iwlagn_txq_ctx_stop(struct iwl_priv *priv) |
949 | { | 949 | { |
950 | int ch; | 950 | int ch, txq_id; |
951 | unsigned long flags; | 951 | unsigned long flags; |
952 | 952 | ||
953 | /* Turn off all Tx DMA fifos */ | 953 | /* Turn off all Tx DMA fifos */ |
@@ -966,6 +966,16 @@ void iwlagn_txq_ctx_stop(struct iwl_priv *priv) | |||
966 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); | 966 | iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG)); |
967 | } | 967 | } |
968 | spin_unlock_irqrestore(&priv->lock, flags); | 968 | spin_unlock_irqrestore(&priv->lock, flags); |
969 | |||
970 | if (!priv->txq) | ||
971 | return; | ||
972 | |||
973 | /* Unmap DMA from host system and free skb's */ | ||
974 | for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) | ||
975 | if (txq_id == priv->cmd_queue) | ||
976 | iwl_cmd_queue_unmap(priv); | ||
977 | else | ||
978 | iwl_tx_queue_unmap(priv, txq_id); | ||
969 | } | 979 | } |
970 | 980 | ||
971 | /* | 981 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 909b42d5d9c..ce368d8d402 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -510,6 +510,7 @@ void iwl_rx_reply_error(struct iwl_priv *priv, | |||
510 | * RX | 510 | * RX |
511 | ******************************************************/ | 511 | ******************************************************/ |
512 | void iwl_cmd_queue_free(struct iwl_priv *priv); | 512 | void iwl_cmd_queue_free(struct iwl_priv *priv); |
513 | void iwl_cmd_queue_unmap(struct iwl_priv *priv); | ||
513 | int iwl_rx_queue_alloc(struct iwl_priv *priv); | 514 | int iwl_rx_queue_alloc(struct iwl_priv *priv); |
514 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, | 515 | void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv, |
515 | struct iwl_rx_queue *q); | 516 | struct iwl_rx_queue *q); |
@@ -534,6 +535,7 @@ int iwl_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq, | |||
534 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, | 535 | void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq, |
535 | int slots_num, u32 txq_id); | 536 | int slots_num, u32 txq_id); |
536 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); | 537 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id); |
538 | void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id); | ||
537 | void iwl_setup_watchdog(struct iwl_priv *priv); | 539 | void iwl_setup_watchdog(struct iwl_priv *priv); |
538 | /***************************************************** | 540 | /***************************************************** |
539 | * TX power | 541 | * TX power |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 7e607d39da1..277c9175dcf 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -86,6 +86,23 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
86 | } | 86 | } |
87 | 87 | ||
88 | /** | 88 | /** |
89 | * iwl_tx_queue_unmap - Unmap any remaining DMA mappings and free skb's | ||
90 | */ | ||
91 | void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id) | ||
92 | { | ||
93 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | ||
94 | struct iwl_queue *q = &txq->q; | ||
95 | |||
96 | if (q->n_bd == 0) | ||
97 | return; | ||
98 | |||
99 | while (q->write_ptr != q->read_ptr) { | ||
100 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
101 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | /** | ||
89 | * iwl_tx_queue_free - Deallocate DMA queue. | 106 | * iwl_tx_queue_free - Deallocate DMA queue. |
90 | * @txq: Transmit queue to deallocate. | 107 | * @txq: Transmit queue to deallocate. |
91 | * | 108 | * |
@@ -96,17 +113,10 @@ void iwl_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq) | |||
96 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | 113 | void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) |
97 | { | 114 | { |
98 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; | 115 | struct iwl_tx_queue *txq = &priv->txq[txq_id]; |
99 | struct iwl_queue *q = &txq->q; | ||
100 | struct device *dev = &priv->pci_dev->dev; | 116 | struct device *dev = &priv->pci_dev->dev; |
101 | int i; | 117 | int i; |
102 | 118 | ||
103 | if (q->n_bd == 0) | 119 | iwl_tx_queue_unmap(priv, txq_id); |
104 | return; | ||
105 | |||
106 | /* first, empty all BD's */ | ||
107 | for (; q->write_ptr != q->read_ptr; | ||
108 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) | ||
109 | priv->cfg->ops->lib->txq_free_tfd(priv, txq); | ||
110 | 120 | ||
111 | /* De-alloc array of command/tx buffers */ | 121 | /* De-alloc array of command/tx buffers */ |
112 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) | 122 | for (i = 0; i < TFD_TX_CMD_SLOTS; i++) |
@@ -132,39 +142,33 @@ void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id) | |||
132 | } | 142 | } |
133 | 143 | ||
134 | /** | 144 | /** |
135 | * iwl_cmd_queue_free - Deallocate DMA queue. | 145 | * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue |
136 | * @txq: Transmit queue to deallocate. | ||
137 | * | ||
138 | * Empty queue by removing and destroying all BD's. | ||
139 | * Free all buffers. | ||
140 | * 0-fill, but do not free "txq" descriptor structure. | ||
141 | */ | 146 | */ |
142 | void iwl_cmd_queue_free(struct iwl_priv *priv) | 147 | void iwl_cmd_queue_unmap(struct iwl_priv *priv) |
143 | { | 148 | { |
144 | struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; | 149 | struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; |
145 | struct iwl_queue *q = &txq->q; | 150 | struct iwl_queue *q = &txq->q; |
146 | struct device *dev = &priv->pci_dev->dev; | ||
147 | int i; | 151 | int i; |
148 | bool huge = false; | 152 | bool huge = false; |
149 | 153 | ||
150 | if (q->n_bd == 0) | 154 | if (q->n_bd == 0) |
151 | return; | 155 | return; |
152 | 156 | ||
153 | for (; q->read_ptr != q->write_ptr; | 157 | while (q->read_ptr != q->write_ptr) { |
154 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) { | ||
155 | /* we have no way to tell if it is a huge cmd ATM */ | 158 | /* we have no way to tell if it is a huge cmd ATM */ |
156 | i = get_cmd_index(q, q->read_ptr, 0); | 159 | i = get_cmd_index(q, q->read_ptr, 0); |
157 | 160 | ||
158 | if (txq->meta[i].flags & CMD_SIZE_HUGE) { | 161 | if (txq->meta[i].flags & CMD_SIZE_HUGE) |
159 | huge = true; | 162 | huge = true; |
160 | continue; | 163 | else |
161 | } | 164 | pci_unmap_single(priv->pci_dev, |
165 | dma_unmap_addr(&txq->meta[i], mapping), | ||
166 | dma_unmap_len(&txq->meta[i], len), | ||
167 | PCI_DMA_BIDIRECTIONAL); | ||
162 | 168 | ||
163 | pci_unmap_single(priv->pci_dev, | 169 | q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd); |
164 | dma_unmap_addr(&txq->meta[i], mapping), | ||
165 | dma_unmap_len(&txq->meta[i], len), | ||
166 | PCI_DMA_BIDIRECTIONAL); | ||
167 | } | 170 | } |
171 | |||
168 | if (huge) { | 172 | if (huge) { |
169 | i = q->n_window; | 173 | i = q->n_window; |
170 | pci_unmap_single(priv->pci_dev, | 174 | pci_unmap_single(priv->pci_dev, |
@@ -172,6 +176,23 @@ void iwl_cmd_queue_free(struct iwl_priv *priv) | |||
172 | dma_unmap_len(&txq->meta[i], len), | 176 | dma_unmap_len(&txq->meta[i], len), |
173 | PCI_DMA_BIDIRECTIONAL); | 177 | PCI_DMA_BIDIRECTIONAL); |
174 | } | 178 | } |
179 | } | ||
180 | |||
181 | /** | ||
182 | * iwl_cmd_queue_free - Deallocate DMA queue. | ||
183 | * @txq: Transmit queue to deallocate. | ||
184 | * | ||
185 | * Empty queue by removing and destroying all BD's. | ||
186 | * Free all buffers. | ||
187 | * 0-fill, but do not free "txq" descriptor structure. | ||
188 | */ | ||
189 | void iwl_cmd_queue_free(struct iwl_priv *priv) | ||
190 | { | ||
191 | struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue]; | ||
192 | struct device *dev = &priv->pci_dev->dev; | ||
193 | int i; | ||
194 | |||
195 | iwl_cmd_queue_unmap(priv); | ||
175 | 196 | ||
176 | /* De-alloc array of command/tx buffers */ | 197 | /* De-alloc array of command/tx buffers */ |
177 | for (i = 0; i <= TFD_CMD_SLOTS; i++) | 198 | for (i = 0; i <= TFD_CMD_SLOTS; i++) |